04/29/2010 继承和消息

继承: 允许创建一个类,作为另一个类精炼(refinement)和特化(specialization).

歌曲  VS  卡拉OK

区别:一首卡拉OK歌曲和歌曲没有什么两样,只是没有主唱的音轨,包括对应的一套歌词以及时间信息。

 

定义一个新的类:KaraokeSong

“< Song” 表示KaraokeSong是Song的子类(subclass),Song是KaraokeSong的超类(superclass).既KaraokeSong的父类是Song.

 

class KaraokeSong < Song                             

  def initialize(name, artist, duration, lyrics)       #lyrics是歌词

    super(name, artist, duration)

    @lyrics  = lyrics

   end

end

 

在最终的系统中,歌词保存在一个对象中,其中包括文本以及时间信息。

 

Ruby的调用机制:

当Ruby遇到方法调用song.to_s时,查看song所属的类,如果该类实现了和消息名称相同的方法,就运行这个方法。否则,Ruby就查看其父类中的方法,然后是祖父类,凡此以往追溯整个祖先链。如果最终在祖先类中没有找到合适的方法,Ruby会导致引发一个错误。

 

例:向song--即karaokeSong类的一个对象--发送消息to_s.

class Song
  def initialize(name, artist, duration)
    @name      = name
    @artist      = artist
    @duration  = duration
  end
  def to_s
    "Song: #@name -- #@artist (#@duration) "
  end
end

class KaraokeSong  < Song
  def initialize(name, artist, duration, lyrics)
    super(name, artist, duration)
    @lyrics  = lyrics
  end
  def to_s                                              
    super + "\n#@lyrics"                              #调用其父类的to_s方法得到歌曲的细节,然后将歌词信息添加上去。
  end
end

song = KaraokeSong.new("LOVE", "Nikey", 250, "Hi,baby,i love you...")
puts song.to_s

输出结果:

Song: LOVE -- Nikey (250)
Hi,baby,i love you...

 

注:若KaraokeSong类中没有定义to_s类,则程序为:

class Song
  def initialize(name, artist, duration)
    @name      = name
    @artist      = artist
    @duration  = duration
  end
  def to_s
    "Song: #@name -- #@artist (#@duration) "
  end
end

class KaraokeSong  < Song

  def initialize(name, artist, duration, lyrics)
    super(name, artist, duration)
    @lyrics  = lyrics
  end

end

song = KaraokeSong.new("LOVE", "Nikey", 250, "Hi,baby,i love you...")
puts song.to_s

输出结果:

Song: LOVE -- Nikey (250)

因为在KaraokeSong类中没有找到要调用的方法to_s,解释器就查看KaraokeSong的父类Song类,结果找到了to_s方法,就按照Song类中定义的to_s的方法进行输出。

 

尽量避免让子类去调用其父类的实例变量来使用这样的编程风格,让每个类处理其自身实现细节的方法。

 

关键字super: 当调用super而不使用参数时,Ruby向当前对象的父类发送一个消息,要求它调用子类中的同名方法。Ruby将原先调用方法时的参数传递给父类的方法。

 

如果定义一个类时,没有指定其父类,Ruby默认以Object类作为其父类。所以Object类的实例方法对Ruby的所有对象都可用。

Object类中有超过35个的实例方法,而to_s是其中之一。

posted @ 2010-04-29 00:46  NikeyL  阅读(143)  评论(0编辑  收藏  举报