代码之家  ›  专栏  ›  技术社区  ›  sarunw

实例变量:self-vs@

  •  173
  • sarunw  · 技术社区  · 15 年前

    下面是一些代码:

    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 self.age 在里面 age_difference_with 方法。

    6 回复  |  直到 9 年前
        1
  •  251
  •   Chuck    15 年前

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

        2
  •  23
  •   tvanfosson    15 年前

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

        3
  •  5
  •   Community CDub    8 年前

    从继承类时受到警告 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
    
        4
  •  2
  •   DigitalRoss    15 年前

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

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

    但是,这是一个不太可能的抽象,毕竟,如果对象的实现发生了变化,那么改变其他方法是合理的,在某种程度上,对象内部的简单引用是完全合理的。

    在任何情况下,抽象的 age 属性仍然无法解释 self 就像普通的一样 年龄 也会调用访问器。

        5
  •  1
  •   blob    9 年前

    第一个答案是完全正确的,但是作为一个相对的新手,我并没有马上明白它意味着什么(给自己发送信息?啊哈…)。我认为一个简短的例子将有助于:

    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
    
        6
  •  -2
  •   LEMUEL ADANE    9 年前

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

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