在这里使用attr_accessor是否更好?

时间:2016-11-15 17:22:36

标签: ruby oop instance-variables attr

我有一个班级QuestionList,用于存储“问题”列表。对象。

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 - 这是否可以在主类中使用?

2 个答案:

答案 0 :(得分: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 :(得分:1)

@questions数组是您班级的私人内部实施细节。它永远不会暴露给客户。原因有很多,其中两个例子是:

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

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