7: More classes and polymorphism 类的多态性
Classes aren’t just stand-alone classes, but they’re actually kind of like a family tree in that they have ancestors. A String, for example, has the Object class as ancestor (yes, Object is also a class). To illustrate which ancestors a class has, we’ll write it down like so:
类不仅仅只是单独的一个类,不同的类之间是有一定的关系的。
就好像是人类跟狗类也是存在一定的关系的一样。
更加具体的,某些类之间是有父子关系的,比如说String类(字符串类),我们来看下面的这个例子:
This is the ancestor line for the String class. The first class that comes before String, Comparable, is the superclass of the String class.
从上面的这个例子中,我们可以清楚的看到String的父子类关系链。
可以看到,String类的父类(Superclass)是Comparable类(可比较类);String类是Comparable类的子类(Subclass)。
The ancestor line of the Fixnum class is this:
再来看一个Fixnum类(整数类)的父子类关系链:
Now let’s say we’re doing 12.odd? #=> false. This method returns whether or not the number is odd (13.odd? would be true).
When you call a method on an object (an instance method), it will look at the highest class there is, which is Fixnum in this case. If that Fixnum class contains an instance method called odd?, it will call that method.
我们写下12.odd?这段代码的时候,对于这段代码来说,我们对12这个整数类的实例调用了odd?方法。
当整数类存在一个叫做odd?的方法时,那么就会直接调用这个odd?方法。
If that Fixnum class does not contain an instance method called odd?, it will look at the class below it, which is Integer. If that Integer class contains an instance method called odd?, it’ll call that. If not, it’ll check Precision, Numeric, Comparable, Object, and then Kernel. If it still hasn’t found it after Kernel, it will raise a NoMethodError. This is the concept of inheritance/polymorphism; a class will inherit all methods from its ancestors.
而如果整数类中不存在一个叫做odd?的方法的话,程序会向上从整数类的父类中继续查找是否有一个叫做odd?的方法,如果有的话就运行这个方法,如果还没有的话,就继续向上查找,有就运行,没有就向上查找,直到Kernel(核心)为止,如果Kernel依然没有,那么就会报错,因为你调用了一个根本不存在的方法。
也就是说,子类会继承父类的全部方法。
Comparable has an instance method called .is_a?, which Strings, Arrays, Floats, Integers and what not all use. But Kernel also has an instance method called .is_a?, which is used by classes that don’t have Comparable (such as NilClass). NilClass’s ancestors are:
我们来看一个is_a?这个方法的例子,这个方法存在于Comparable类中,虽然NilClass并不是Comparable的子类,但是我们依然可以对nil对象使用这个方法,这就是因为在Kernel中也存在着一个叫做is_a?的方法。
我们来看一下NilClass的父子类关系链:
So when you call 14.is_a?(Fixnum), you’re calling it on Comparable.
When you call nil.is_a?(Fixnum), you’re calling it on Kernel.
所以,当你写14.is_a?(Fixnum)的时候,程序调用的其实是Comparable里面的is_a?。
而当你写nil.is_a?(Fixnum)的时候,程序调用的其实是Kernel里面的is_a?。
Speaking of .is_a?, if you give it a class that is a part of the class’s inheritance tree, it’ll also return true.
另外,我们也可以用is_a?来检查一个对象的父类是什么,请看下面的例子:
Every single object in Ruby inherits both Kernel and Object, which means var.is_a?(Object) is always going to return true no matter what (as long as var exists). The same applies to var.is_a?(Kernel).
Classes aren’t just stand-alone classes, but they’re actually kind of like a family tree in that they have ancestors. A String, for example, has the Object class as ancestor (yes, Object is also a class). To illustrate which ancestors a class has, we’ll write it down like so:
类不仅仅只是单独的一个类,不同的类之间是有一定的关系的。
就好像是人类跟狗类也是存在一定的关系的一样。
更加具体的,某些类之间是有父子关系的,比如说String类(字符串类),我们来看下面的这个例子:
This is the ancestor line for the String class. The first class that comes before String, Comparable, is the superclass of the String class.
从上面的这个例子中,我们可以清楚的看到String的父子类关系链。
可以看到,String类的父类(Superclass)是Comparable类(可比较类);String类是Comparable类的子类(Subclass)。
The ancestor line of the Fixnum class is this:
再来看一个Fixnum类(整数类)的父子类关系链:
Now let’s say we’re doing 12.odd? #=> false. This method returns whether or not the number is odd (13.odd? would be true).
When you call a method on an object (an instance method), it will look at the highest class there is, which is Fixnum in this case. If that Fixnum class contains an instance method called odd?, it will call that method.
我们写下12.odd?这段代码的时候,对于这段代码来说,我们对12这个整数类的实例调用了odd?方法。
当整数类存在一个叫做odd?的方法时,那么就会直接调用这个odd?方法。
If that Fixnum class does not contain an instance method called odd?, it will look at the class below it, which is Integer. If that Integer class contains an instance method called odd?, it’ll call that. If not, it’ll check Precision, Numeric, Comparable, Object, and then Kernel. If it still hasn’t found it after Kernel, it will raise a NoMethodError. This is the concept of inheritance/polymorphism; a class will inherit all methods from its ancestors.
而如果整数类中不存在一个叫做odd?的方法的话,程序会向上从整数类的父类中继续查找是否有一个叫做odd?的方法,如果有的话就运行这个方法,如果还没有的话,就继续向上查找,有就运行,没有就向上查找,直到Kernel(核心)为止,如果Kernel依然没有,那么就会报错,因为你调用了一个根本不存在的方法。
也就是说,子类会继承父类的全部方法。
Comparable has an instance method called .is_a?, which Strings, Arrays, Floats, Integers and what not all use. But Kernel also has an instance method called .is_a?, which is used by classes that don’t have Comparable (such as NilClass). NilClass’s ancestors are:
我们来看一个is_a?这个方法的例子,这个方法存在于Comparable类中,虽然NilClass并不是Comparable的子类,但是我们依然可以对nil对象使用这个方法,这就是因为在Kernel中也存在着一个叫做is_a?的方法。
我们来看一下NilClass的父子类关系链:
So when you call 14.is_a?(Fixnum), you’re calling it on Comparable.
When you call nil.is_a?(Fixnum), you’re calling it on Kernel.
所以,当你写14.is_a?(Fixnum)的时候,程序调用的其实是Comparable里面的is_a?。
而当你写nil.is_a?(Fixnum)的时候,程序调用的其实是Kernel里面的is_a?。
Speaking of .is_a?, if you give it a class that is a part of the class’s inheritance tree, it’ll also return true.
另外,我们也可以用is_a?来检查一个对象的父类是什么,请看下面的例子:
Every single object in Ruby inherits both Kernel and Object, which means var.is_a?(Object) is always going to return true no matter what (as long as var exists). The same applies to var.is_a?(Kernel).