关于Metaclass得理解

 今天看《Applying UML and Pattens》的时候看到metaclass这个词,是在描述调用静态函数的时候,记得以前就看到过这个关键字,但是并没有深入研究,今天google了一个多小时,小有心得,总结如下:

 

在很多语言中,会为每个类生成另一个类,这个生成类用来描述你所声明的类,称为metaclass,而声明的那个类其实是metaclass的一个实例。

什么意思?下面是我看网上的一篇文章之后自己的理解,由于我对ruby不是很熟,可能理解有偏差。

举个例子来说,你在Ruby中声明一个Person类,但在运行期间,假如生成的类的名字是(Person),这个类是Class类的子类,它用来描述Person类的相关信息,包括类的名字,超类类型等等。这个(Person)类就是一个metaclass,而你声明的Person类虽然我们平时称它为一个Person类,但其实他是(Person)的一个实例,所以准确的说Person是一个对象,而不是类。

 

Ruby中有这样的语句:

    1. def Person.getTotal  
    2.   puts "How many people on earth?"  
    3. end 

意思是定义一个Person的方法,名字叫getTotal,这个方法是类方法,类似于Java,C++中的静态方法,也就是说通过Person的实例是不能调用的。那么现在我们看看Person.getTotal这样的调用语句,上面我们谈到了,Person实际上是一个对象,所以这个语句不正是我们平时熟悉类似与str.toString()这样的调用语句么?

 

晕头转向了吧,呵呵,说了半天我自己都晕了,对Ruby不是很了解啊。下面我就拿Java为例子来说:

在《Applying UML and Pattens》有这样一段话:

in Java and Smalltalk, all classes are conceptually or literally instances of class Class; in .NET classes are instances of class Type. The classes Class and Type are metaclasses, which means their instances are themselves classes. A specific class, such as class Calendar, is itself an instance of class Class. Thus, class Calendar is an instance of a metaclass!

 

什么意思呢?下面我结合自己的理解举个例子,如果不对还行高手指出:

 

在Java中声明一个Person类,运行期间会发生什么?JVM会根据这个Person类生成一个Class类的对象,这个对象在运行期间用来描述Person类(这类似与我们上面Ruby那个例子中说的Person类实际上是个对象),执行Person p = new Person();后,p并不是直接指向实例数据,而是指向一个handle,这个handle中有两个指针,一个指向实例数据,另一个就是指向类数据,也就是JVM生成的那个描述Person类的那个对象。

 

那么我们如何获得这个生成的对象呢?p.getClass(); 和Person.class就是干这事的,他可以获得描述Person类的对象的句柄,由于他是Class类的对象,所以我们可以调用他的成员函数,如newIntance,getConstructor等等,等一下,这几个方法名怎么这么熟悉呢?没错,相信一应该想到了吧,反射!是的,我的理解java中的反射应该就是这样实现的。

 

那么静态方法呢?我们也可以解释为什么static成员变量和static方法分别被成为是类方法、类成员了,因为它们都是生成的描述Person类的对象的普通成员,应该用Person.fun()的方式调用。

 

所以,画Sequence Diagram是,如果是静态方法调用的话,要化成Metaclass的成员调用形式。于是又有一个问题不是很清楚了,C++的静态函数调用并不是Metaclass形式实现的,那么C++的静态成员函数的调用应该怎么画呢?

 

总结一下,我觉得其实java.lang.Class被称为metaclass有一些不恰当,它只是实现了metaclass中的一部分功能罢了。

 

下面是我在网上看到一个网友总结的,感觉总结的很不错:

Some environments - such as Smalltalk - automatically define another class for each class you define. This is called a metaclass. Your class definition describes the data structure and methods of your class. The metaclass describes the data structure and methods of the class description - yes, the description of your class is also an object: an instance of the corresponding metaclass.
Exactly one such instance of each metaclass exists at runtime. If you add "class instance variables" and "class methods" to your class, what really happens is that fields and instance methods are added to the metaclass instead. I.e. you can change the structure and behavior of your class description.
In Java, all class descriptions look and work the same: They are instances of java.lang.Class. You cannot add any methods or fields there for some class descriptions where you think you need this; you can use the existing ones, though. E.g. getName() or newInstance() or getMethod()...
This is how the literature defines metaclasses in object orientation. Java obviously does not support metaclasses. However, even in Java you have exactly one class description for each loaded class at runtime. And you can do a lot using their methods (getMethod(), getConstructor(), isArray(), getInterfaces() etc... i.e. using Reflection)
You get the class description for an Object's class by calling getClass() on the object. If you know the classname, you can append .class to it to accomplish the same, e.g. String.class, which uses the class loader of the code that contains this expression for locating the class. Static method forName() in java.lang.Class has an overloaded variant where you can pass in the classname (fully qualified!) and the class loader to be used.
By the way: As we mentioned, in Systems having metaclasses, a "class method" is just a normal instance method of a metaclass, can be called on the instance of a metaclass and is dynamically bound and thus supports polymorphism. Java's static methods have often been compared to such class methods but in fact are - as the name reveals - just static methods, i.e. statically bound, non-polymorphic methods; consequently the syntax for calling them requires no receiver object. The only instance methods acting on class descriptions are those of java.lang.Class.
(sidenote: "class instance variables" in Smalltalk are instance variables of metaclasses; you might have guessed that they should be called "class variables" but these are yet another thing and those two should not be confused when working with Smalltalk. But for Java programmers this does, of course, not matter ;-)

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值