vala 如何允许定义没有默认构造函数的 GObject?
How does vala allow defining GObjects with no default constructor?
Vala tutorial 表明 classes 可以用 GObject 风格或类似于 Java / C# 等风格的构造函数编写。
教程显示这完全独立于 class 是否继承自 Glib.GObject。(编辑:我对教程感到困惑在 Glib.Object
和 Object
之间切换。在 Vala 中有一个隐含的 using Glib
,所以两者是相同的)。
如果 Glib.GObject subclass 的定义没有默认构造函数(使用 Java/C# 样式),那么我是否认为必须定义隐式默认构造函数?对于 GObject,可能会将所有字段都填充为二进制零(根据 GObject 初始化)?
另见 Initialize a GObject with parameters which are not GObject properties?
让我们用valac -C
找出答案。
示例代码:
class MySuper : Object
{
private int i;
private int j;
public MySuper (int i)
{
this.i = i;
j = 1;
}
}
class MyDerived : MySuper
{
public MyDerived ()
{
base (10);
}
}
生成的(相关部分)C 代码如下所示:
MySuper* my_super_construct (GType object_type, gint i) {
MySuper * self = NULL;
gint _tmp0_ = 0;
self = (MySuper*) g_object_new (object_type, NULL);
_tmp0_ = i;
self->priv->i = _tmp0_;
self->priv->j = 1;
return self;
}
MySuper* my_super_new (gint i) {
return my_super_construct (TYPE_MY_SUPER, i);
}
MyDerived* my_derived_construct (GType object_type) {
MyDerived * self = NULL;
self = (MyDerived*) my_super_construct (object_type, 10);
return self;
}
MyDerived* my_derived_new (void) {
return my_derived_construct (TYPE_MY_DERIVED);
}
对 valac 生成的内容的一些观察:
- MySuper 和 MyDerived 都有一个
_construct
和 _new
函数。
my_super_construct
只调用 g_object_new
.
my_derived_construct
仅调用 my_super_construct
(后者又调用 g_object_new
.
所以一切都被 Vala 编译器很好地链接起来,C#/Java 风格的构造函数被翻译成 GObject 风格的构造。
关于成员的初始化:如果您不在 Vala 代码中提供初始化,生成的构造函数也不会初始化任何东西。
所有这一切都是通过 Vala 在幕后为您完成的。你不应该担心代码生成的细节,但如果你愿意,你总是可以使用 -C
...
Vala 会自动在 C 代码中创建一个构造函数。这遵循 *_new 命名模式。所以最简单的例子:
void main () {
new ExampleWithoutExplicitConstructor ();
}
class ExampleWithoutExplicitConstructor {
}
如果您使用 valac --ccode example.vala
编译它并查看生成的 C 代码,您将看到 _vala_main
调用 example_without_explicit_constructor_new ()
,然后调用 example_without_explicit_constructor_construct ()
。 example_without_explicit_constructor_construct ()
然后为该类型调用 g_object_new ()
。作为 g_object_new
创建类型的一部分,它将调用 example_without_explicit_constructor_instance_init ()
可以初始化任何变量的地方。
这是一个更复杂的示例,它继承自 Object
,完整的 GObject
class 也是如此,它有一个带有默认值的字段和一个带有默认值的 属性默认值:
void main () {
new ExampleWithoutExplicitConstructor ();
}
class ExampleWithoutExplicitConstructor:Object {
private string example_field = "default";
public string an_object_property { get;
set;
default = "this object properties default string";
}
}
你会从 C 代码中注意到 _new
、_construct
、g_object_new
、_instance_init
模式是相同的。 Vala 所做的是设置 _instance_init
来初始化字段和属性的默认值。
Public 没有默认值的字段为空。您将看到它们出现在保存实例数据的 struct
的定义中。私有字段类似,但在实例的私有 struct
中保存。您可以通过尝试示例来亲眼看到这一点。
Vala tutorial 表明 classes 可以用 GObject 风格或类似于 Java / C# 等风格的构造函数编写。
教程显示这完全独立于 class 是否继承自 Glib.GObject。(编辑:我对教程感到困惑在 Glib.Object
和 Object
之间切换。在 Vala 中有一个隐含的 using Glib
,所以两者是相同的)。
如果 Glib.GObject subclass 的定义没有默认构造函数(使用 Java/C# 样式),那么我是否认为必须定义隐式默认构造函数?对于 GObject,可能会将所有字段都填充为二进制零(根据 GObject 初始化)?
另见 Initialize a GObject with parameters which are not GObject properties?
让我们用valac -C
找出答案。
示例代码:
class MySuper : Object
{
private int i;
private int j;
public MySuper (int i)
{
this.i = i;
j = 1;
}
}
class MyDerived : MySuper
{
public MyDerived ()
{
base (10);
}
}
生成的(相关部分)C 代码如下所示:
MySuper* my_super_construct (GType object_type, gint i) {
MySuper * self = NULL;
gint _tmp0_ = 0;
self = (MySuper*) g_object_new (object_type, NULL);
_tmp0_ = i;
self->priv->i = _tmp0_;
self->priv->j = 1;
return self;
}
MySuper* my_super_new (gint i) {
return my_super_construct (TYPE_MY_SUPER, i);
}
MyDerived* my_derived_construct (GType object_type) {
MyDerived * self = NULL;
self = (MyDerived*) my_super_construct (object_type, 10);
return self;
}
MyDerived* my_derived_new (void) {
return my_derived_construct (TYPE_MY_DERIVED);
}
对 valac 生成的内容的一些观察:
- MySuper 和 MyDerived 都有一个
_construct
和_new
函数。 my_super_construct
只调用g_object_new
.my_derived_construct
仅调用my_super_construct
(后者又调用g_object_new
.
所以一切都被 Vala 编译器很好地链接起来,C#/Java 风格的构造函数被翻译成 GObject 风格的构造。
关于成员的初始化:如果您不在 Vala 代码中提供初始化,生成的构造函数也不会初始化任何东西。
所有这一切都是通过 Vala 在幕后为您完成的。你不应该担心代码生成的细节,但如果你愿意,你总是可以使用 -C
...
Vala 会自动在 C 代码中创建一个构造函数。这遵循 *_new 命名模式。所以最简单的例子:
void main () {
new ExampleWithoutExplicitConstructor ();
}
class ExampleWithoutExplicitConstructor {
}
如果您使用 valac --ccode example.vala
编译它并查看生成的 C 代码,您将看到 _vala_main
调用 example_without_explicit_constructor_new ()
,然后调用 example_without_explicit_constructor_construct ()
。 example_without_explicit_constructor_construct ()
然后为该类型调用 g_object_new ()
。作为 g_object_new
创建类型的一部分,它将调用 example_without_explicit_constructor_instance_init ()
可以初始化任何变量的地方。
这是一个更复杂的示例,它继承自 Object
,完整的 GObject
class 也是如此,它有一个带有默认值的字段和一个带有默认值的 属性默认值:
void main () {
new ExampleWithoutExplicitConstructor ();
}
class ExampleWithoutExplicitConstructor:Object {
private string example_field = "default";
public string an_object_property { get;
set;
default = "this object properties default string";
}
}
你会从 C 代码中注意到 _new
、_construct
、g_object_new
、_instance_init
模式是相同的。 Vala 所做的是设置 _instance_init
来初始化字段和属性的默认值。
Public 没有默认值的字段为空。您将看到它们出现在保存实例数据的 struct
的定义中。私有字段类似,但在实例的私有 struct
中保存。您可以通过尝试示例来亲眼看到这一点。