如果忽略方法重写,你可以将Java类和方法看作是C风格的
struct
和一组对这些
struct
进行操作的函数的组合。例如,如果你有如下类:
public class MyJavaClass {
private int x;
public int getX() {
return x;
}
public int setX(int value) {
x = value;
}
}
这类似于编写以下C代码:
struct MyJavaClass {
int x;
};
int MyJavaClass_getX(struct MyJavaClass* this) {
return this->x;
}
void MyJavaClass_setX(struct MyJavaClass* this, int value) {
this->x = value;
}
主要思想是,一个方法类似于一个函数,它将接收器对象作为隐式的“this”参数。在C中,您必须显式将接收器作为参数传递给函数,而在Java中,这通过
object.method()
语法隐含地完成。
如果开始介绍方法重写,这就变得有点复杂,因为调用对象上的方法取决于对象的动态类型,而不是静态类型。一种模拟方法是使用称为“虚表”或“虚函数表”的东西,因为C++中有
virtual
关键字。思路是每个对象都存储一个函数指针表,每个被覆盖的函数对应一个指针,并且当在对象上调用方法时,适当的函数指针将从表中选择并调用。因此,更正确的是,上面的Java对象可能看起来像这样:
struct MyJavaClass_Vtable {
void (*getX)(struct MyJavaClass* this);
void (*setX)(struct MyJavaClass* this, int value);
};
struct MyJavaClass {
struct MyJavaClass_Vtable* vtable;
int x;
};
int MyJavaClass_getX(struct MyJavaClass* this) {
return this->x;
}
void MyJavaClass_setX(struct MyJavaClass* this, int value) {
this->x = value;
}
struct MyJavaClass_Vtable MyJavaClassVtableInstance = {
&MyJavaClass_getX,
&MyJavaClass_setX
};
无论何时创建了
MyJavaClass
的一个实例,你需要像下面这样设置它的虚函数表:
struct MyJavaClass* mjc = malloc(sizeof *mjc);
mjc->vtable = &MyJavaClassVtableInstance;
那么,在 Java 中调用函数时,可以这样写:
myJavaClass.getX();
在C语言中,它看起来像:
myJavaClass->vtable->getX(myJavaClass);
就某种意义上来说,Java类只是带有一些额外元信息的结构体。当然,对于程序员来说,它看起来完全不同 - 有封装、多态性、更严格的类型系统等等 - 但在本地代码层面上,普通的C结构体和Java类可能看起来非常相似。
希望这可以帮到你!
C
没有继承的概念。你应该把它发表为一个答案。 - Mahesh