@ foo,self.foo和foo之间的区别?

时间:2016-07-27 12:03:23

标签: ruby

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

所以在这个例子中,它使用了所有两种类型,@ song和song。

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

然后在这个例子中,

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

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

好的,所以我忘了再说一件事。在上面的第一个代码片段中,对于方法print_songs,为什么我能够使用songs.each而不是@ songs.each?我原本以为它会产生错误的未定义歌曲。

2 个答案:

答案 0 :(得分:2)

  

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

使用该方法更灵活。您可以从了解自己获取/存储数据的确切方式中抽象自己。您对实现细节的依赖程度越低,以后您就越容易更改代码。

一个小例子,考虑songs

的这种实现
def songs
  @songs ||= []
  @songs
end
在调用此方法之前,

@songs可能已经或未被赋值。但它并不关心。它确保@songs 具有合理的默认值。这个概念被称为&#34;懒惰初始化&#34;如果直接使用实例变量,它会非常繁琐且容易出错。

因此,如果有疑问,请始终使用方法。

答案 1 :(得分:1)

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关键字始终可用,它指向当前对象。在Ruby中,所有方法调用都包含发送给接收方的消息。换句话说,在对象上调用所有方法。调用该方法的对象是接收者,方法是消息。如果我们打电话给&#34; foo&#34; .upcase,&#34; foo&#34; object是接收者,upcase是消息。如果我们在调用方法时没有指定对象(接收者),则会在自身对象上隐式调用它。

班级的自我关键字

在类中但在任何实例方法之外使用时,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>

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