实例变量:self vs @

sar*_*unw 175 ruby instance-variables self

这是一些代码:

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
Run Code Online (Sandbox Code Playgroud)

我想知道的是两者的区别@age,并self.ageage_difference_with方法.

Chu*_*uck 255

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

  • 我曾经在rails中读过一本书并且不理解这个self和@之间的区别,所以我应该总是在我的方法中使用self.var_name(不是setter和getter)来使用公共接口创建我的数据,I花时间在getter和setter中定义它,对吧? (2认同)
  • ...英语...你所说的许多事情是什么意思。我没有得到最后两个例子。 (2认同)

tva*_*son 23

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

  • 哦,因为self.age可以引用实例变量或实例方法? (15认同)

pro*_*eek 7

当你继承一个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()
Run Code Online (Sandbox Code Playgroud)

将返回

30
nil
Run Code Online (Sandbox Code Playgroud)

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

nil
30
Run Code Online (Sandbox Code Playgroud)

随着类的定义

class Node2
    attr_accessor :value
    def initialize(value)
        @value = value
    end
    def show()
        p @value
        p self.value
    end
end
Run Code Online (Sandbox Code Playgroud)

你应该提供构造函数.

n2 = Node2.new(30)
n2.show()
Run Code Online (Sandbox Code Playgroud)

将返回

30
30
Run Code Online (Sandbox Code Playgroud)

  • 感谢 @Prosseek 的例子,我目前正在学习 Ruby on Rails,这正是让我觉得 Ruby 不必要地复杂的行为&gt;.&lt;。 (2认同)

blo*_*lob 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
Run Code Online (Sandbox Code Playgroud)

  • 这个例子让事情变得更加混乱。 (10认同)
  • 很抱歉,这个例子对我来说没有得到足够的评论。我无法理解你的推理。 (2认同)