实例变量: self vs@

下面是一些代码:

class Person
def initialize(age)
@age = age
end


def age
@age
end


def age_difference_with(other_person)
(self.age - other_person.age).abs
end


protected :age
end

我想知道的是在 age_difference_with方法中使用 @ageself.age的区别。

43896 次浏览

区别在于,它将方法的使用与方法的实现隔离开来。如果属性的实现发生变化——比如保留出生日期,然后根据现在和出生日期之间的时间差计算年龄——那么取决于方法的代码就不需要变化。如果它直接使用该属性,则更改将需要传播到代码的其他区域。从这个意义上说,直接使用属性比使用类提供的接口更脆弱。

没什么区别。我怀疑这样做只是为了看到 self.ageother_person.age彼此接近的纪录片价值。

我认为这种使用确实允许将来编写一个实际的 getter 函数,它可能做一些比返回一个实例变量更复杂的事情,在这种情况下,方法不需要更改。

但是,毕竟,如果对象的实现发生了变化,那么更改其他方法就是合理的,在某种程度上,对象本身内部的简单引用是完全合理的。

在任何情况下,age属性的抽象仍然不能解释 self的显式使用,因为仅仅是简单的 age也会调用访问器。

写入 @age可直接访问实例变量 @age。编写 self.age告诉对象向自己发送消息 age,它通常会返回实例变量 @ageーー但是可以执行许多其他操作,这取决于在给定子类中如何实现 age方法。例如,您可能有一个 MiddleAgeSocialite 类,它总是报告其年龄比实际年龄小10岁。或者更实际地说,PersisentPerson 类可以从持久性存储中惰性地读取该数据,并将其所有持久性数据缓存在一个散列中。

当您从 Struct.new继承一个类时,请注意这是生成初始化器(如何在 Ruby 中生成初始化程序?)的一种简单方法

class Node < Struct.new(:value)
def initialize(value)
@value = value
end
def show()
p @value
p self.value # or `p value`
end
end


n = Node.new(30)
n.show()

会回来的

30
nil

但是,当您删除初始化程序,它将返回

nil
30

用类定义

class Node2
attr_accessor :value
def initialize(value)
@value = value
end
def show()
p @value
p self.value
end
end

您应该提供构造函数。

n2 = Node2.new(30)
n2.show()

会回来的

30
30

@ 年龄-绝对是实例变量的年龄

Age-指的是实例属性 age。

第一个答案是完全正确的,但是作为一个相对的新手,我不是很清楚它的含义(给自己发信息?嗯...)。我认为一个简短的例子会有所帮助:

class CrazyAccessors
def bar=(val)
@bar = val - 20 # sets @bar to (input - 20)
end
def bar
@bar
end


def baz=(value)
self.bar = value # goes through `bar=` method, so @bar = (50 - 20)
end


def quux=(value)
@bar = value     # sets @bar directly to 50
end
end


obj  = CrazyAccessors.new
obj.baz = 50
obj.bar  # => 30
obj.quux = 50
obj.bar  # => 50