[software development] GObject简介和入门指引(五)再谈一点其他的事
Tofloor
poster avatar
enforcee
deepin
2023-08-11 07:25
Author

这将是这次写作的最后一章了。不知道大家有没有从头看过来,也不知道大家能得到多少收获?在结束之前,还有最后的一点内容要和大家说。

GObject虽然设计巧妙,理念先进,但是晦涩、麻烦、难学一直都是他挥之不去的阴影。在我们努力学过之后,似乎这种印象反而加深了呢。GObject已经用尽全力为开发者降低使用难度,但是我们也清楚,既然选择了C语言,就没办法让语法更简洁。有没有一种可能,我们能做到语法像Java、C#那样简洁直观,而又能保证运行效率,不舍弃C语言的基础设施吗?

答案是,有的。那就是Vala语言。我花费几分钟,就把之前的那个案例重写了一遍,请看:

manage-student.vala内容:

class Manage.Student : GLib.Object {
	/*
	  可以真正把所有成员都放在一起了!
	 */
	public enum Gender {
		MALE = 0,
		FEMALE = 1
	}
	public const short YEAR_NOW = 2023;
	/*
	  枚举和常量也变短了!
	 */
        private string name = "吴名氏";
	private Gender gender = Gender.MALE;
	private uchar grade = 1;
	private short admission_year = 2023;
	/*
	  可以直接在声明时赋予初值!
	  而且现在也可以使用public公共变量了!
	 */
	public void update_info (string name, Gender gender, uchar grade, short admission_year) {
		this.name = name;
		this.gender = gender;
		if (grade > 4) {
			grade = 4;
		}
		this.grade = grade;
		this.admission_year = admission_year;
	}
	/*
	  方法可以不用写自己作为参数了!
	 */
	private short years_to_graduate () {
		return ( 5 - this.grade + YEAR_NOW - this.admission_year );
	}

	public void self_introduction () {
		stdout.printf ("我的名字是%s, %d年入学,", this.name, this.admission_year);
		if (this.years_to_graduate () > 4) {
			stdout.printf ("已经毕业了。");
		} else {
			stdout.printf ("还有%d年毕业。", this.years_to_graduate ());
		}
	}

	public void describe_gender () {
		if (this.gender == Gender.MALE){
			stdout.printf ("我是男生。");
		} else {
			stdout.printf ("我是女生。");
		}
	}
	/*
	  不用再写八股文了!
	 */
}

manage-usa-student.vala内容:

class Manage.UsaStudent : Manage.Student {
	private string usa_gender = "未知";

	public void update_info (string name, string gender, uchar grade, short admission_year) {
		base.update_info (name, Manage.Student.Gender.MALE, grade, admission_year);
		/*
		  调用基类的方法,就用base关键字。
	     */
		this.usa_gender = gender;
	}

	public void describe_gender () {
		stdout.printf("我的性别是%s。", this.usa_gender);
	}
	/*
	  变得很简短了!
	 */
}

main.vala内容:

int main (string[] args) {

	Manage.Student student_a = new Manage.Student ();
	student_a.self_introduction ();
	student_a.describe_gender ();
	stdout.printf ("\n");
	/*
	  赋值函数:
	 */
	student_a.update_info ("小明", Manage.Student.Gender.FEMALE, 3, 2023);
	student_a.self_introduction ();
	student_a.describe_gender ();
	stdout.printf ("\n");
	/*
	  如果使用指针
	  Manage.Student * student_a = new Manage.Student ();
	  那么可以使用手动方法释放内存
	  delete student_a
	  否则就都是自动控制了。
	 */

        Manage.UsaStudent student_b = new Manage.UsaStudent ();
	student_b.update_info ("John", "你猜", 1, 2020);
	student_b.self_introduction ();
	/*
	  不需要类型转换,就能调用父类的方法。
	*/
	student_b.describe_gender ();
	/*
	  本类和父类有同名函数时,会选择使用本类的函数。
	  如果想使用父类的函数,就强行转换吧。
	 */
	stdout.printf ("\n");

	return 0;
}

甚至连编译的命令都那么简洁:

valac ./main.vala ./manage-student.vala ./manage-usa-student.vala

什么,这当真不是C#吗?我读的书少不要骗我。虽然观感很像,但是Vala其实还是GObject的心。Vala用GLib作为标准库,把源代码编译成C语言或GObject,然后再用C编译器编译成程序文件。甚至,他还给喜欢python的开发者带来了另一种选择:Genie语言,有着和python类似的语法,也用valac命令来编译。

那么除了Vala之外,我们还能在其他地方用上GObject吗?答案也是肯定的,而且你也完全不用再学习一门新的语言。还记得我在第一章中提到的GObject Introspection吗?他能为相当多的语言打开GObject的大门。如果你用js写过GNOME Shell的插件(imports.gi),如果用python写GTK应用(import gi),以及perl,java,ruby,lua,rust等,GObject变得无处不在,而GLib也为许多缺乏基础设施的语言提供了强力支持。曾经,GObject只是GTK的一小部分,而GTK还只是Gimp的图形组件,也许他的原作者也没能想到,一个小小的异想天开居然能如此地改变开源软件世界的面貌。为生活所迫的我们总是思考各种技术的意义和价值,但是我相信,技术的趣味更是吸引人们不断探索的动力。希望大家都能带着第一次Hello World的热情,来创造更美好的未来吧。


资源:

Vala主页:https://vala.dev/

Vala文档:https://wiki.gnome.org/Projects/Vala/Documentation

Genie文档:https://wiki.gnome.org/Projects/Genie

Vala API:https://valadoc.org/

GObject Introspection文档:https://gi.readthedocs.io/en/latest/

GNOME开发主页:https://developer.gnome.org/index.html

GTK主页:https://gtk.org/

Reply Favorite View the author
All Replies
enforcee
deepin
2023-08-11 07:32
#1

我过去的文章合集:https://bbs.deepin.org/post/259765
blush

Reply View the author
jjcui8595
deepin
2023-08-11 14:31
#2

like

Reply View the author
fuuko
deepin
2023-08-11 15:34
#3

虽然不喜欢GObject那坨东西,但还是给你点个赞like

Reply View the author
阿尼樱奈奈
Moderator
2023-08-11 15:58
#4

like

Reply View the author
sammy-621
deepin
2023-08-11 16:28
#5

很不错,收藏下来慢慢看

Reply View the author
W2J
deepin
2023-08-12 03:01
#6

感谢enforcee大佬深入浅出的文章。五篇找来一一读过,收获不小。

原来GObject和GLIB,结合NameSpace重构后,已华丽转身,变成了简约易用的Vala/Genie。

关键是它们还能还原成C语言搭配Glib库,奠定了基础又灵活的Abi业界地位。

Reply View the author