2016-11-15 59 views
2

我有一个类QuestionList存储'问题'对象的列表。在这里使用attr_accessor是否更好?

class QuestionList 

    attr_accessor :questions 

    def initialize 
     @questions = [] 
    end 

end 

我再补充问题列表,然后选择“询问”这些问题从我的主类像这样:

list = QuestionList.new 
list.questions << Question.new(5, 3) 
list.questions << Question.new(1, 5) 
list.questions << Question.new(2, 4) 

list.questions.each do |question| 
    puts "#{question.ask}" 
end 

其中Question.ask只是输出的问题作为一个字符串。

我不确定从主类使用<<运算符写入实例变量是多么的可以接受,list.questions.push(Question.new(5, 3))在主类中更加不清楚。

最好是有一个QuestionsList.add_question(question)方法?

list.questions.each的情况也是如此 - 是否可以在主类中使用?

回答

1

我认为您在这里使用的attr_accessor没问题,不过取决于您继续添加多少功能,它可能会更清晰地限制该类的功能。

关于使用QuestionList中的方法的问题,这可能归结为可读性。但是,首先需要注意的是:以QuestionsList.add_question(question)为例。这将创建一个类方法。你真正想要的是一个实例方法,它会读作list.add_question(question),因为你已经创建了一个列表的实例。 This blog post有关于类和实例方法之间区别的一些很好的信息。

我个人发现实例方法会最清楚地表达您的意图。我会写出来QuestionList如下:

class QuestionList 

    def initialize 
    @questions = [] 
    end 

    def add_question(question) 
    @questions << question 
    end 

    def print_all_questions_in_list 
    @questions.each do |question| 
     puts "#{question.ask}" 
    end 
    end 

end 

This SO post对Ruby的attr方法的一些优秀的信息,如果你想获得更多的信息出现。

1

@questions数组是您班级的私人内部实现细节。它应该永远不会接触到客户。造成这种情况的原因有很多,其中有两个例子:

  • 您过度推销接口:现在,您的所有客户都依赖于它作为数组。如果您以后想要将其更改为其他内容,该怎么办?一个文本文件?数据库?一个web服务?
  • 您公开了破坏对象不变量的操作:例如,客户端可以为该数组添加整数。或者nil。或其他任何不是Question

如何你存储你的问题应该是一个实现细节。 QuestionList应该有管理问题列表的方法。它应该有一个each方法(和include Enumerable)和一个add方法(可能与<<混淆)。如果有意义的话,也许还可以是[]。如果方便的话,可以简单地将这些方法委托给数组,但重点是:如果您稍后决定不使用数组,则可以在没有任何人注意的情况下这样做。您可以决定仅支持您实际想要支持的那些方法,而不是所有的〜Array的〜100种方法。