ruby 示例变量:self vs @

huus2vyu  于 2023-06-22  发布在  Ruby
关注(0)|答案(7)|浏览(92)

下面是一些代码:

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的区别。

5ssjco0h

5ssjco0h1#

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

u7up0aaq

u7up0aaq2#

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

v6ylcynt

v6ylcynt3#

当您从Struct.new继承一个类时要注意,这是一种生成初始化器(How to generate initializer in 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
raogr8fs

raogr8fs4#

第一个答案是完全正确的,但作为一个相对的新手,我并不立即清楚它意味着什么(发送消息给自己?)嗯哼...)。我想一个简短的例子会有所帮助:

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
dfty9e19

dfty9e195#

没有任何区别。我怀疑这样做只是为了看到self.ageother_person.age彼此靠近的文献价值。
我认为这种用法确实允许将来编写一个实际的getter,它可能会做一些比返回一个示例变量更复杂的事情,在这种情况下,方法不需要改变。
但这是一个不太可能担心的抽象,毕竟,如果对象的实现改变了,改变其他方法是合理的,在某种程度上,对象本身的简单引用是完全合理的。
无论如何,age属性的抽象仍然不能解释self的显式使用,因为普通的age也会调用访问器。

bxgwgixi

bxgwgixi6#

self.age是指@age的getter方法。请考虑以下示例:

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

  # def age
  #   @age
  # end

  def age_difference_with_1(other_person_age)
    (@age - other_person_age).abs
  end

  def age_difference_with_2(other_person_age)
    (self.age - other_person_age).abs
  end
end

person = Person.new(25)
person.age_difference_with_1(40)
# => 15
person.age_difference_with_2(40)
# NoMethodError (undefined method `age' for #<Person:0x0000000108034298 @age=25>)

注意,person.age_difference_with_2(40)引发NoMethodError,因为对应的getter方法age不存在。取消注解后,此异常消失:

def age
    @age
  end

或者,您也可以使用以下行定义getter方法:

attr_reader :age
qybjjes1

qybjjes17#

@age -绝对是示例变量age
self.age -引用示例属性的年龄。

相关问题