190

这是一些代码:

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

我想知道的是 using@ageself.ageinage_difference_with方法之间的区别。

4

6 回答 6

277

写入@age直接访问实例变量@age。写入self.age告诉对象向自己发送消息age,消息通常会返回实例变量@age——但可以根据age给定子类中方法的实现方式做任何数量的其他事情。例如,您可能有一个 MiddleAgedSocialite 类,它总是报告其年龄比实际年龄小 10 岁。或者更实际地,PersistentPerson 类可能会懒惰地从持久存储中读取该数据,将其所有持久数据缓存在哈希中。

于 2009-11-07T15:00:53.523 回答
24

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

于 2009-11-07T14:41:52.700 回答
10

当您继承一个类时,请注意生成初始化程序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
于 2015-11-14T02:03:35.640 回答
7

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

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
于 2016-06-04T13:52:17.980 回答
2

没有任何区别。我怀疑这样做只是为了看到self.ageother_person.age靠近彼此的文献价值。

我想 use 确实允许在将来编写一个实际的 getter,这可能会做一些比仅仅返回一个实例变量更复杂的事情,在这种情况下,方法不需要改变。

但这是一个不太可能担心的抽象,毕竟,如果对象的实现发生了变化,那么改变其他方法是合理的,在某些时候,对象本身内的简单引用是完全合理的。

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

于 2009-11-07T14:53:29.090 回答
-2

@age - 绝对是实例变量 age

self.age - 指实例属性年龄。

于 2016-03-06T00:35:03.037 回答