【问题标题】:Difference between @foo, self.foo, and foo?@foo、self.foo 和 foo 之间的区别?
【发布时间】:2016-12-01 10:22:09
【问题描述】:
class Artist
 @@song_count = []
 attr_accessor :name, :songs

 def initialize(name)
  @name = name
  @songs = []
 end

 def add_song(song)
  @songs << song
 end

 def print_songs
  songs.each {|song| puts song.name}
 end
end

所以在本例中,它使用了所有两种类型,@songs 和歌曲。

我很难理解为什么要使用这些,而不是使用@songs 来处理所有内容。

然后在这个例子中,

def add_song(song)
 self.songs << song
 song.artist = self
 @@song_count +=1
end

为什么使用 self.songs 而不是 @songs?

好的,所以我忘了再说一件事。在上面的第一个代码 sn-p 中,对于方法 print_songs,为什么我可以使用 song.each 而不是 @songs.each?我预计它会生成错误未定义的歌曲。

【问题讨论】:

标签: ruby


【解决方案1】:

为什么使用 self.songs 而不是 @songs

使用方法更灵活。您将自己从了解它如何获取/存储数据中抽象出来。您对实现细节的依赖越少,您以后更改代码就越容易。

一个小例子,考虑songs的这个实现

def songs
  @songs ||= []
  @songs
end

@songs 在调用此方法之前可能已分配值,也可能未分配值。但它不在乎。它确保 @songs 确实 具有合理的默认值。这个概念被称为“惰性初始化”,如果直接使用实例变量,这样做非常繁琐且容易出错。

因此,当有疑问时,请始终使用方法。

【讨论】:

    【解决方案2】:

    foo@foo 之间的区别

    实例变量

    实例变量在实例方法中定义,它们的名字以@开头。它们的值只能在设置它的特定对象内访问。换句话说,当我们修改实例变量的值时,更改仅适用于该特定实例。与仅在定义它们的方法中可用的局部变量不同,实例变量可由对象内的所有方法(类的实例方法)访问。实例变量是 Ruby 类中最常用的变量类型。

    class Car
      attr_reader :color
    
      def set_color(color_receiverd_as_argument)
        @color = color_receiverd_as_argument
      end
    end
    
    car1 = Car.new
    car1.color     # Output: => nil
    car1.set_color "black"
    car1.color     # Output: => "black"
    
    car2 = Car.new
    car2.set_color "silver"
    car2.color    # Output: => "silver"
    

    在上面的例子中,请注意:

    • 在初始化之前尝试访问实例变量不会引发异常。它的默认值为 nil。
    • 在 Car 类的一个实例中更改颜色变量的值不会影响其他实例中相同变量的值。

    局部变量

    类中的局部变量与 Ruby 中的任何其他局部变量一样。它只能在创建它的确切范围内访问。如果在方法中定义,则仅在该方法中可用。

    class Car
      def initialize
        wheels = 4
      end
    
      def print_wheels
        print wheels
      end
    end
    
    c = Car.new
    c.print_wheels        # Output: NameError: undefined local variable or method `wheels'…
    


    self 关键字

    self 关键字始终可用,它指向当前对象。在 Ruby 中,所有方法调用都包含发送给接收者的消息。换句话说,所有方法都在一个对象上调用。调用方法的对象是接收者,方法是消息。如果我们调用“foo”.upcase,“foo”对象是接收者,而大写是消息。如果我们在调用方法时不指定对象(接收者),则会在 self 对象上隐式调用。

    类级别的自我关键字

    当在类中但在任何实例方法之外使用时,self 指的是类本身。

    class Foo
      @@self_at_class_level = self
    
      def initialize
        puts "self at class level is #{@@self_at_class_level}"
      end
    end
    
    f = Foo.new     # Output: self at class level is Foo
    

    实例方法中的self关键字

    当在实例方法中时,self 关键字引用该特定实例。换句话说,它指的是它被调用的对象。

    class Meditation
      def initialize
        puts "self within an instance method is #{self}"
      end
    end
    
    zazen = Meditation.new     # Output: self within an instance method is #<Meditation:0x00000000ab2b38>
    

    请注意,#&lt;Meditation:0x00000000ab2b38&gt; 是 zazen 对象的字符串表示形式,它是 Meditation 类的一个实例。

    【讨论】:

    • 所有有效信息,但都没有直接回答问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-04
    • 2016-09-09
    • 2012-07-26
    • 2017-03-14
    • 2017-02-03
    • 1970-01-01
    相关资源
    最近更新 更多