下面的示例test4.vala
编译并运行:
//// compile with: valac test4.vala
//~ public class TestClass : GLib.Object { // error: redefinition of ‘struct _TestClass’
//~ public int x = 0;
//~ public int y = 0;
//~ public int z = 0;
//~ }
public Test App;
public class Test : GLib.Object {
public class TestClass : GLib.Object { //current
public int x = 0; //current
public int y = 0; //current
public int z = 0; //current
} //current
public TestClass mytc;
public void SetVars() {
mytc = new TestClass();
stdout.printf("SetVars called, %p\n", mytc);
}
public Test(string[] args){
stdout.printf("Test() ctor: ok\n");
stdout.flush();
}
public static int main (string[] args) {
App = new Test(args);
App.SetVars();
stdout.printf("main called\n");
return 0;
}
}
但是,如果我注释了标记为“当前”的行,并且取消注释了注释的代码,则会出现此错误:
$ valac test4.vala && ./test4
/tmp/test4.vala.c:64:8: error: redefinition of ‘struct _TestClass’
struct _TestClass {
^~~~~~~~~~
/tmp/test4.vala.c:20:16: note: originally defined here
typedef struct _TestClass TestClass;
^~~~~~~~~~
error: cc exited with status 256
Compilation failed: 1 error(s), 0 warning(s)
我仍在尝试嘲笑Vala,但是这有点让我感到困惑-为什么我不能在与main
相同的级别上编译另一个类,但是我不得不“另外”包含另一个主应用程序类中的课程?
答案 0 :(得分:4)
它与GObject的工作方式及其命名约定有关。 GObject手册中有more details,所以在这里我不会深入探讨……
创建对象时,在Vala中将其称为Foo
,将在生成的C中创建两个结构:Foo
和FooClass
。前者是人们在API中最常使用的东西,并且代表Foo
的实例,而后者则用于保存有关Foo
类本身的信息;虚拟函数指针是一件大事。
因此,对于您上面的代码,生成的代码将包含用于外部类的Test
和TestClass
,以及用于内部类的TestTestClass
和TestTestClassClass
。取消注释其余代码后,它将尝试生成TestClass
和TestClassClass
,其中前者将与已经存在的外部类的*Class
结构冲突。>
您可以使用以下命令更轻松地重现该问题:
public class Test : GLib.Object { }
public class TestClass : GLib.Object { }
基本上,不要调用类*Class
。