在ruby中直接使用实例变量是不好的形式?

时间:2012-04-02 18:18:06

标签: ruby coding-style instance-variables

你是否应该总是在ruby中创建访问者(用于阅读和/或写作)?如果你有一个不打算在外面重用的类,我不能直接使用实例变量吗?

我遇到的一个问题是在测试中隐藏@instance_vars会有问题。

3 个答案:

答案 0 :(得分:3)

实验变量在测试方面无关紧要。您应该测试方法,以验证它们是否产生了正确的结果。

为属性定义reader方法时,会将该属性公开给世界。如果属性的值来自实例变量,数据库,文件,运行时计算等等,则无关紧要。人们可以调用方法来获取值。

同样,当您为属性定义编写器方法时,如果需要,您可以让每个人都知道他们可以设置它。价值在哪里并不重要。

只有您的方法定义您的公共API。其他一切都是实施细节。

在您的类定义中,直接访问实例变量肯定没有害处:

@variable = :value

如果只需要简单的分配,就没有理由调用方法。当然,有时您需要更复杂的功能。延迟初始化,例如:

def variable
  @variable ||= :value
end

# ...

variable.to_s

如果您的方法仅供内部使用,则不应将其包含在公共API中。将其标记为私人:

private :variable

老实说,Ruby中没有任何东西被锁定。即使没有setter方法,人们也可以轻易篡改你的对象,如果他们真的想:

class << (object = Object.new)
  private
  def variable; @variable end
end

object.variable
# NoMethodError: private method `variable' called

# send bypasses access control
object.send :variable
# => :value

object.instance_variables
# => [:@variable]
object.instance_variable_get :@variable
# => :value

object.instance_variables.each do |variable|
  object.instance_variable_set variable, nil
end
object.instance_variable_get :@variable
# => nil

答案 1 :(得分:1)

我认为,在设置或执行获取/设置新值的任务之前,当您想要验证新变量时,访问器可能会对某些事情有所帮助。如果你确定你不需要它,我认为最好留下实例变量。否则你可以在开头创建那些,所以你不必在以后有大量代码时创建它们,你可以节省很多时间。

答案 2 :(得分:1)

实例变量旨在在相关实例的上下文中使用。如果您需要与其他对象或其他实例交换数据,则应根据需要使用attr_readerattr_accessor公开数据,如果不是为了方便而编写自己的方法。

访问者方法充当网守,并为您提供验证外部呼叫者不会破坏您的内部状态的机会。面向对象设计的一个原则是该对象承担筛选输入的责任。你如何处理错误的输入取决于你,无论是忽略它,抛出异常,还是记录错误等等。

如果您没有处理错误输入并因此而导致崩溃,则最终成为您的“错误”并且您将处于堆栈跟踪的顶部。之前拒绝错误值会在问题发生时准确显示问题,而不是在执行过程中,当您可能已经忘记了该分配的来源时。

通常,您不希望人们访问您的数据,除非他们有充分的理由。直接访问和修改另一个对象的实例变量是不好的形式。

有些语言甚至无法直接改变对象的内部状态,但Ruby在这方面非常随意。但是,仅仅因为可以做某事并不意味着应该这样做。

当您定义访问者时,如果您在该实例的实现中使用它们,则由您决定。有时直接访问它们更方便,调用@var而不是self.var,但有时使用访问器提供实例变量不具备的附加功能。由于您只有一个控制点,它还可以在以后更轻松地重构您的应用程序。