刚刚接触Ruby不久,觉得Ruby也挺好玩的。
而在学的过程中,发现了Ruby中比较特别的地方:类方法和实例方法。
在Ruby中类方法和实例方法是有区别的,Ruby的类方法能被类对象调用,而实例方法就被实例对象调用。或许你已经想到,没错,类也是对象,这是Ruby和C++/Java的一个显著不同,在C++/Java中,类仅仅是一个数据抽象,并没有类也是对象这样的概念。而在Ruby中存在着元类的概念,类也是对象,所有类都是元类的实例对象。
Ruby的的实例方法和Java等其他语言的定义类似,直接用
class className
...
def instance_methodName(args)
end
end
或者用类外定义(和这个类似)
class className
...
end
class className
def another_instance_methodName(args)
end
end
定义实例方法。
而类方法的定义,就在方法前加入类名称或者self关键字
class className
...
def self.class_methodName(args)
end
end
或者用类外定义
class className
...
end
class<<ClaFun
def self.another_class_methodName(args)
end
end
定义类方法。
下面是例子,我们先定义一个Person类,然后就定义了一个实例方法talk方法和一个sleep的类方法
class Person
def initialize(name,age=18)
end
def talk
print("this is instance method talk")
end
def self.sleep
print("this is class method sleep")
end
end
他们的调用方式就如下了
Preson.sleep #调用self.sleep方法 输出"this is class method sleep"
aPerson=Person.new
aPerson.talk #调用talk方法 输出"this is instance method talk"
#aPerson.sleep #报错
从他们两的定义方法的形式可以看出,虽然他们的都是写在一个类里面,习惯了C++/Java的就容易认为他们的级别是相同的(都属于className下)。其实不然,他们并不是在同一个“类”中,前者在Class类的实例中,而后者在className类的实例中。就本例而言,self.sleep是一个类方法,而talk是一个实例方法。对一个特定对象来说,每个对象都会有一个talk方法的一份拷贝,他们是相互隔离互不影响的;而类方法则是所有类成员可以共享操作的方法。
这个证明过程很简单:
puts Person.methods
puts
puts aPerson.methods #和Person.instance_methods等同
就会发现sleep方法在Person.methods里面,而talk就在aPerson.methods里面。
那如果在类方法里买呢调用实例方法,或者在实例方法调用类方法呢?
根据刚才的理论,就可以如下调用
类方法里买呢调用实例方法用 self.new.instance_methodName(args)
def self.sleep
self.new.talk #实例化一个对象再调用
print("this is class method sleep \n")
end
实例方法调用类方法则用 self.class.class_methodName(args)
def talk
self.class.sleep #寻找类的方法
print("this is instance method talk \n")
end
而从另一个角度“存取控制”去看这个问题的话,类方法就相当于className类对象的私有的方法,实例对象不能直接调用,证明这在刚才调用aPerson.sleep的时候就知道了
aPerson.sleep #报错 private method `sleep' called for #<Person:0xb77075e4> (NoMethodError)
所以在在className里面把类方法声明为Public,类的实例对象就可以直接调用了(就看在实际应用中有没有必要这样做了)
class className
...
public :sleep
end
aPerson.sleep #没有报错,并且在aPerson.methods里也确实出现了sleep方法,但是貌似方法里面的代码没有执行,在这里就是没有输出,一个奇怪的地方。
个人觉得这种机制和JS的prototype是有相似之处的,但不是完全相似。
阐述就到这里吧,第一次发文章…………呵呵~~