您是否应始终在ruby中创建附件(用于阅读和/或书写)?如果你有一个不想在外面重用的类,我不能直接使用实例变量吗?在ruby中直接使用实例变量是不是很糟糕?
我碰到的一个问题是,在测试中将@instance_vars
残缺掉是有问题的。
您是否应始终在ruby中创建附件(用于阅读和/或书写)?如果你有一个不想在外面重用的类,我不能直接使用实例变量吗?在ruby中直接使用实例变量是不是很糟糕?
我碰到的一个问题是,在测试中将@instance_vars
残缺掉是有问题的。
当涉及到测试时,实例变量并不重要。您应该测试您的方法,以验证它们是否会产生正确的结果。
当您为属性定义读取器方法时,会将该属性公开给世界。如果属性的值来自实例变量,数据库,文件,运行时计算或任何其他内容,则无关紧要。人们可以调用该方法来获取价值。
同样,当你为一个属性定义一个编写器方法时,你让每个人都知道他们可以设置它,如果他们需要的话。价值在哪里并不重要。
只有你的方法定义你的公共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
如果一个方法使用了一个实例变量,我需要能够在测试过程中将它存根:http://stackoverflow.com/questions/9971192/stub-an-instance-variable-using-mocha – m33lky 2012-04-02 21:38:07
@ m33lky,你不' t存根变量,则存根方法。我不熟悉'mocha',但是这里是如何在'RSpec':'(obj = MyClass.new).stub(:method1).and_return:new_value'中完成的。之后,'obj.method1'将返回':new_value'。 – 2012-04-02 22:03:06
对不起,这是一个不好的例子。我是单位测试方法本身。它有更多的逻辑,但它取决于一个实例变量。 – m33lky 2012-04-02 22:07:59
我认为accessor是更多的东西,可以帮助你有些时候,当你想在设置或执行任务获取/设置新值之前验证新变量。如果你确定你不需要它,我认为最好留在实例变量中。否则,您可以在开始时创建这些代码,以便在您有大量代码时您不必在稍后创建它们,并且可以节省大量时间。
实例变量是为了将有问题的实例的上下文中使用。如果您需要与其他对象或其他对象交换数据,则应根据需要使用attr_reader
或attr_accessor
来暴露它们,前提是不要编写自己的方法来实现此目的。
访问器方法充当关守,并提供机会让您验证外部调用者不会弄乱您的内部状态。面向对象设计的一个原则是对象承担筛选输入的责任。如何处理错误的输入取决于您,无论是忽略它,抛出异常还是在其他事件中记录错误。
如果您没有处理错误的输入,并因此而崩溃,它最终会成为您的“错误”,您将位于堆栈跟踪的顶部。先前拒绝错误的值会在问题发生的时候显示出问题,而不是在执行的后面,当时您可能已经失去了分配的来源。
通常,您不希望人们访问您的数据,除非他们有充分的理由。直接访问和修改另一个对象的实例变量是不好的形式。
有些语言甚至使得几乎不可能直接改变对象的内部状态,但Ruby在这方面相当随意。尽管如此,仅仅因为可以做的事情并不意味着它应该。
当您定义访问器时,是否在该实例的实现中使用它们取决于您。有时直接访问它们会更方便,因此调用@var
而不是self.var
,但有些情况下使用访问器会提供实例变量不支持的其他功能。由于您拥有单一的控制点,因此它还可以让您的应用程序更轻松地重构。
你可能会觉得这很有趣:http://talklikeaduck.denhaven2.com/2008/02/15/best-practice-patterns-accessors-and-encapsulation – 2012-04-02 22:10:14
你能举一个你说什么的例子吗? – 2012-04-02 23:17:54