ruby系列教材(9):Inheritance and Messages

上一篇 / 下一篇  2008-02-02 14:54:22 / 个人分类:Ruby

Inheritance相信大家已经很熟悉了,就是继承,从一个class里面派生出另外一个subclass,例如:

 

class KaraokeSong < Song

  def initialize(name, artist, duration, lyrics)

    super(name, artist, duration)

    @lyrics = lyrics

  end

end

 

结果是什么?我们在Song的基础上,建立了新的类别,KaraokeSong,在这个例子里面,它实际上是在Song里面添加了一个新的variable,以求获得一种新的states,我们前面说过,ruby way中,可以添加方法来实现添加属性,但是我们为什么不这么做,而使用了继承来达到这个目的?ruby way给我们的方式是:

 

class Song

  def initialize(name,artist,duration,lyrics)

    @name=name

    @artist=artist

    @duration=duration

    @lyrics=lyrics

  end

end

 

这里注意:我们下面谈到的属性,只是意义上的属性,不是ruby里面的属性(attributes)

为什么不建议大家使用第2种方式?显而易见的是,一类事物,它的固有属性是不变的,如果它的属性都变了,也就发生了质变,它就不在是此物了,由此我们相信,一个构造完善的类,属性是一定的,但是就如前面我们说的,在不同的人看来,对这些属性的操作上,有不同的方法,而方法在特定的领域变化将是非常剧烈,我们不可能在构造类的时候了解所有应该建立的方法,因为在某些领域,我们不可能是专家,我们也无法了解这么多,所以构造的类,包含的方法也是有限的,因此,当ruby涉及到一些专业领域,添加method就为我们的工作提供了极大的方便。

依然是这句话:我们认为属性的变化,使得物体发生质变,它已经不是我们开始认为的那类事物了,而第2种方式,改变属性以后,还认为这类物品还是以前的那类物品。比如说,我们在车上装了翅膀,让车飞起来,我们还能硬要说它是车吗?至少应该称之为飞车。所以,在属性变化的时候,我们应该另构着一个类。使用第2种方式不仅是意义上的问题,还会带来副作用,我们也可以这样看,一个类,因为某个愿意,我们为它添加了一种新的适合于某个专业领域的属性,结果是什么?结果是:一个不熟悉某个领域的人,要建立这个类的时候,使用new,这是要提供必要的parameters,由于不了解特定领域,而不能给出或者不能正确给出一个parameter,使得这个object都处于一种rick state,危险状态,在实际编程中,你会理解这种危险状态。因此在这里,我们偏好使用inheritance。但是不是说完全就不能使用方式2来override一个initialize method,以求修改它的instance variable,在某些情况下可以,比如说,设计者本身就没有设计完善这个类,没有包括所有普遍属性,比如粗心的设计或者考虑不够周全,使得car类,没有轮子这个属性,这是我们可以添加,当然这样会带来复杂和麻烦,就好像一个根基都倾斜的比萨斜塔,想要把它修正一样的困难和危险,但是这总比使用一辆没有轮子的车好。

 

 

方法的调用:

在ruby里面,方法被调用的时候,先在调用方法的object属于的class里面寻找,如果没有再在superclass里面找,一直向前。这里我们认为method属于某个class,而不是属于某个特定的object,最后如果都没有找到调用的方法,发生error---NoMethodError.

 

 

为什么使用super:

1)

class Song
  def initialize(a,b,c)
    @a=a
    @b=b
    @c=c
  end
 
  def to_s
    "#@a,#@b,#@c"
  end
end

class OtherSong < Song
  def initialize(a,b,c,d)
    #super(a,b,c)
    @aa=a
    @bb=b
    @cc=c
    @d=d
  end
end

song = OtherSong.new("a","b",123,"c")
print song.to_s                                   #使用superclass的to_s方法

 

结果:

,,                           

 

2)

class Song
  def initialize(a,b,c)
    @a=a
    @b=b
    @c=c
  end
 
  def to_s
    "#@a,#@b,#@c"
  end
end

class OtherSong < Song
  def initialize(a,b,c,d)
    super(a,b,c)                            #使用super
    @d=d
  end
end

song = OtherSong.new("a","b",123,"c")
print song

 

结果:

a,b,123

 

大家应该都看见了结果,不使用super时,如果我们对Song的内部实现不了解,结果就产生了错误,这就使得我们“要开车,必须要知道怎么制造车”,这个比喻不一定十分合理。但是上面的例子已经告诉我们一个事实,我们必须捅破superclass的实现,以求的subclass的正确实现,这无疑增加了复杂度,为了建立一个类,我们要学习它的superclass。所以使用super,这使得superclass的implements被隐藏起来,我们对此不需要关心,同样的理由,我们会用在很多设计的很多方面,给出一个跟直观的约定:“我们尽可能的使用methods,而不是使用variables来实现功能,特别时在类的构造的时候,尽量使用superclasses的methods,而不是它的variables

 

 

super用法:

super表示的是一个method,这个method是与调用它的方法同名的在superclass里面的method,简化此句为:

super表示superclass里面与调用super的方法同名的方法

例如:

class Song
  def initialize(a,b,c)
    @a=a
    @b=b
    @c=c
  end
 
  def to_s
    "#@a,#@b,#@c"
  end
end

class OtherSong < Song
  def initialize(a,b,c,d)
    super(a,b,c)                              #调用superclass里面的initialize方法
    @d=d
  end
  def to_s
    super + "c"                              #调用superclass里面的to_s方法
  end
end

 

由此,superclass里面是什么,这个super就表示成什么样子。比如上面,initialize在superclass里面有3个参数,那么下面的super也有3个参数,to_s没有参数,super也没有参数,必须一致,不然就发生错误(ArgumentError)。

为了更好的说明这个问题,我再写了一个例子:

class Song
  def initialize(a,b,c)
    @a=a
    @b=b
    @c=c
  end
 
  def to_s
    "#@a,#@b,#@c"
  end
end

class OtherSong < Song
  def initialize(a,b,c,d)
    super(a,b,c)
    @d=d
  end
  def to_s
    super(1) + "c"                          #使用了一个Argument
  end
end

song = OtherSong.new("a","b",123,"c")
print song

 

结果:

in `to_s': wrong number of arguments (1 for 0) (ArgumentError)
from a.rb:19:in `to_s'
from a.rb:24

 

 

再论super

super提供了一个可以方便访问superclass的机制,使得我们不必刺穿method的真相(我们也不想这么做),就可以获取superclass赋予我们的操控力。

 

 

object is An Object

所有的classes都是inheritance Objecgt class,假如我们写一个class,没有制定继承对象,那么这个class将默认继承Object class,这样有什么好处?好处就是我们马上获得了一些特殊的能力,比如说 to_s,每个object都有 to_s 方法,这个方法来源于Object,从某种意义上来说,强制的继承于Object(不论什么类,它的祖先ancestor,都是Object,所以说是强制继承)这种方式提供了一种约束,拿to_s方法来说,也许每个人都有不同的方法来表示 to_s 这个方法,结果造成了混乱的命名,A喜欢用toString,B喜欢getString,这带来了很多的不方便,使用的不方便,还有一些特殊功能的实现也不方便,这种约定,被称之为习惯,在ruby里面我们获得一种习惯,就是当把对象字符串化的时候,我们用to_s,“习惯是一种力量”,陈安之这么认为过,David也这么认为,所以,rails才会这么简单,易用


TAG: Ruby

 

评分:0

我来说两句

我的栏目

日历

« 2024-05-06  
   1234
567891011
12131415161718
19202122232425
262728293031 

数据统计

  • 访问量: 22878
  • 日志数: 47
  • 建立时间: 2008-01-29
  • 更新时间: 2008-02-02

RSS订阅

Open Toolbar