Monday, October 20, 2008

(21)对象类和对象类型

有很多种方法可以获得一个对象的类是什么:
o = "test"  # 定义一个字符串值
o.class # 得到这个对象对于的类String



如果你想对类的集成结构感兴趣,你可以通过调用superclass方法获得:
o.class                       # String:o是一个字符串对象
o.class.superclass # Object: 字符串对象的父类是Object
o.class.superclass.superclass # nil: Object没有父类。

在Ruby1.9中Object不再是跟类:
Object.superclass             # BasicObject:在 1.9中Object的父类是BaseObject
BasicObject.superclass # nil: BasicObject 没有父类

那么,如果想比较一个对象的类是否为某个类,可以直接使用==操作:
o.class == String       # true 

instance_of? 可以完成相同的操作,这种做法看起来更简洁:
o.instance_of? String   # true

通常你可能希望判断一个对象是否是某个类的子类,你可以通过is_a?方法或者kind_of?方法:
x = 1                    # 定义一个对象
x.instance_of? Fixnum # true: 判断x是否是一个Fixnum
x.instance_of? Numeric # false: instance_of? 不能判断x是否为Numeric的子类
x.is_a? Fixnum # true
x.is_a? Integer # true
x.is_a? Numeric # true
x.is_a? Comparable # true: 是否实现了Comparable
x.is_a? Object # true 任何对象都是Object的子类

Ruby还定义了=== 操作符来完成is_a?相同的操作:
Numeric === x            # true: x is_a Numeric

在Ruby中我们通过不关心我们使用的对象的类型,我们只关心我们可以调用对象的那些方法,比如<<操作,在数组、字符串或者文件对象中,他意味着向对象增加内容,而对于整数对象,<<意味着对象的左位移操作。我们可以使用respond_to?方法来判断一个对象是否存在某个我们想要的方法。
o.respond_to? :"<<"  # 返回true,如果存在 << 操作。


但是这个方法的缺点是,你只知道有这样一个方法,但是你知道这个方法接受什么参数。比如对于整型<<期望的参数是一个整数,但是如果你给出的是一个字符串,那么这里会抛出异常。不幸的是,对此没有一个通用的解决方法,一个临时的方法是结合is_a?方法:
o.respond_to? :"<<" and not o.is_a? Numeric

No comments: