Vala

维基百科,自由的百科全书
跳转到导航 跳转到搜索
Vala
File:Vala Logo New.svg
编程范型面向对象结构化指令式
实现者Jürg Billeter, Raffaele Sandrini
发行时间2006年,​20年前​(2006
当前版本
    Module:EditAtWikidata第29行Lua错误:attempt to index field 'wikibase' (a nil value)
    类型系统静态类型, 强类型
    操作系统所有支持GLib的平台
    许可证GNU宽通用公共许可证2.1+
    文件扩展名.vala, .vapi
    网站vala.dev
    受影响于
    C, C++, C#, D, Java, BOO

    Vala是一门面向对象编程语言,由自举编译器产生C语言代码和使用GObject系统,允许在GNOME运行时库的基础上使用大量现代的编程技巧。通过使用GLibGObject,Vala提供了动态类型系统和基于引用计数(reference counting)系统的存储器管理的功能。

    描述[编辑]

    Vala是一门编程语言,结合了脚本语言的高级编程语言建造时间性能,与低级的编程语言运行时间性能。相较于用C写成的应用和库,它致力于将现代编程语言特征带给GNOME开发者,而不用强加任何额外的运行时间要求,并且不用使用不同的ABI。Vala的语法类似于C#,并为了更好的适应GObject类型系统而做了修改[1]

    Vala由Jürg Billeter构想,并由他和Raffaele Sandrini实现,他希望开发GNOME应用能有对C语言的更高级替代者。他们的确喜欢C#的语法和语义,但不想使用Mono,故而他们在2006年5月完成了一个编译器。最初它使用C来引导英语Bootstrapping (compilers),一年后(在2007年7月的版本0.1.0发行中),Vala编译器实现了自举

    版本历史[编辑]

    版本 发行日期[2] 注释
    停止支持: 0.0.1 2006-07-15
    停止支持: 0.1.0 2007-07-09
    停止支持: 0.10.0 2010-09-18
    停止支持: 0.20.0 2013-05-27
    停止支持: 0.30.0 2015-09-18
    停止支持: 0.40.0 2018-05-12 稳定长期支持
    停止支持: 0.42.0 2018-09-01
    停止支持: 0.44.0 2019-05-09
    停止支持: 0.46.0 2019-09-05
    停止支持: 0.48.0 2020-03-03 稳定长期支持
    停止支持: 0.50.0 2020-09-10
    最新版本: 0.40.25 2021-01-11 稳定长期支持
    停止支持: 0.52.0 2021-05-17
    停止支持: 0.54.0 2021-09-16
    停止支持: 0.56.0 2022-03-17 稳定长期支持
    最新版本: 0.48.25 2022-09-16 稳定长期支持
    最新版本: 0.56.17 2024-04-19 稳定长期支持
    格式:
    停止支持
    支持中
    最新预览
    旧版本只列入最初发行时间

    语言设计[编辑]

    特征[编辑]

    Vala使用GLib和它的子模块(GObject、GModule、GThread、GIO)作为核心库,它们支持多数操作系统,并提供:平台无关线程输入/输出文件管理网络套接字插件正则表达式等。Vala的语法目前支持如下现代语言特征:

    图形用户界面可以使用GTK部件工具箱Glade GUI建造器英语Graphical user interface builder来开发。

    内存管理[编辑]

    对于内存管理,GType或GObject系统提供引用计数。在C语言中,编程者必须手工管理增加和移除引用,而在Vala中,管理这种引用计数是自动化的,如果编程者使用语言内置引用类型而非普通指针的话。唯一需要当心的是避免生成引用环,因为在这种情况下内存管理系统不能正确工作,此时需要使用Vala自带的week关键字标注弱引用解决。[3]

    对于不支持引用计数的类型,Vala也支持按照生命周期自动释放内存的非引用计数内存管理;Vala还可以通过指针手工内存管理。[4]

    绑定[编辑]

    Vala意图提供但现存C库的运行时间访问,特别是基于GObject的库,而不需要运行时绑定。要通过Vala使用一个由C语言编写的库,全部所需就是一个API文件(.vapi),包含采用Vala语法的类和方法声明。但是不支持C++库。目前在Vala的每次发行中,都包括了GTK以及大部分的GNU项目和GNOME平台的vapi文件。还有用Vala写的一个库叫做Gee,为常用数据结构提供基于GObject的接口和类[5]

    为从用其他语言比如C#写的应用访问Vala库,写绑定生成器也应当是容易的,因为Vala解析器被写为一个库,所以所有运行时信息在生成一个绑定的时候都是可获得到的。

    工具[编辑]

    编辑器[编辑]

    Vala的开发工具近些年来有了显著改进。下面是具有支持Vala编程的插件的一些流行IDE文本编辑器

    代码智能[编辑]

    目前,有两个活跃开发的语言服务器为Vala提供了代码智能

    • vala-lang/vala-language-server,设计用于支持LSP的任何编辑器,包括VSCode、vim和GNOME Builder[9]
    • esodan/gvls,目前是Vala在GNOME Builder中的缺省语言服务器,它对支持LSP的任何编辑器提供支持[10]

    建造系统[编辑]

    目前,有一些建造系统支持Vala,包括AutomakeCMakeMeson[11]

    调试[编辑]

    对Vala程序的调试可以使用GDBLLDB英语LLDB (debugger)。对于IDE

    示范代码[编辑]

    一个简单的“Hello world”程序:

    void main () {
        print ("Hello World\n");
    }
    

    面向对象[编辑]

    下面是更复杂的一个版本,表现了Vala的一些面向对象的特征:

    class HelloWorld: Object {
    	private uint year = 0;
    	
    	public HelloWorld () {
    	}
    	
    	public HelloWorld.with_year (int year) {
    		if (year > 0)
    			this.year = year;
    	}
    
    	public void greeting () {
    		if (year == 0)
    			print ("Hello World\n");
    		else
    			/* Strings prefixed with '@' are string templates. */
    			print (@"Hello World, $(this.year)\n"); 
    	}
    }
    
    void main (string[] args) {
    	var helloworld = new HelloWorld.with_year (2021);
    	helloworld.greeting ();
    }
    

    因为在GObject库的情况下,Vala不支持多重继承,但是Vala中的类可以实现任何数量的接口,它可以包含它们的方法的缺省实现。下面一段代码展示具有缺省实现的Vala接口(有时称为mixin):

    using GLib;
    
    interface Printable {
    	public abstract string print ();
    
    	public virtual string pretty_print () {
    		return "Please " + print ();
    	}
    }
    
    class NormalPrint: Object, Printable {
    	string print () {
    		return "don't forget about me";
    	}
    }
    
    class OverridePrint: Object, Printable {
    	string print () {
    		return "Mind the gap";
    	}
    
    	public override string pretty_print () {
    		return "Override";
    	}
    }
    
    void main (string[] args) {
    	var normal = new NormalPrint ();
    	var overridden = new OverridePrint ();
    
    	print (normal.pretty_print ());
    	print (overridden.pretty_print ());
    }
    

    信号和回调[编辑]

    下面是基本例子,展示如何定义一个信号于非紧凑(compact)的一个类中,它拥有用Vala通过GLib建造的一个信号系统。接着注册回调函数到这个类的一个实例的这个信号。这个实例可以发送这个信号,而连接到这个实例的每个回调函数(也叫做处理器),将安它们连接上的次序来调用:

    class Foo {
        public signal void some_event ();   // 定义一个信号
    
        public void method () {
            some_event ();                  // 发送这个信号(回调得以调用)
        }
    }
    
    void callback_a () {
        print ("Callback A\n");
    }
    
    void callback_b () {
        print ("Callback B\n");
    }
    
    void main () {
        var foo = new Foo ();
        foo.some_event.connect (callback_a);      // 连接回调函数
        foo.some_event.connect (callback_b);
        foo.method ();
    }
    

    线程[编辑]

    在Vala中新线程是代码的一部分,比如要求在运行时间并发执行的一个函数。新线程的创建和同步是用时GLib中的Thread类完成的,它在创建新线程时接受一个函数作为参数,如下面(非常简化的)例子所示:

    int question(){
        // 一些print操作 
        for (var i = 0; i < 3; i++){
            print (".");
            Thread.usleep (800000);
            stdout.flush ();
        }
    
        return 42;
    }
    
    void main () {
        if (!Thread.supported ()) {
            printerr ("Cannot run without thread support.\n");
            return;
        }
        print ("The Ultimate Question of Life, the Universe, and Everything");
        // 泛型参数是返回值的类型
        var thread = new Thread<int> ("question", question);
    
        print(@" $(thread.join ())\n");
    }
    

    图形用户界面[编辑]

    使用GTK来创建一个图形用户界面的"Hello, World!"程序:

    int main (string[] args) {
        var app = new Gtk.Application (
            "com.example.App",
            ApplicationFlags.DEFAULT_FLAGS
        );
        
        app.activate.connect (() => {
            var win = new Gtk.ApplicationWindow (app) {
                title = "Hello, World!",
                default_width = 350,
                default_height = 70
            };
      
            var label = new Gtk.Label ("Hello, World!");
            win.child = label;
            win.present ();
        });
        return app.run (args);
    }
    

    在GTK 4平台上,需要以下命令来编译这一示例:

    valac --pkg gtk4 hellogtk.vala
    

    参见[编辑]

    • Genie,基于Vala编译器的具有近似Python语法的一种语言。
    • Shotwell,用Vala写的图片组织器。
    • Geary英语Geary (e-mail client),用Vala写的邮件客户端。
    • elementary OS,具有大多用Vala编程的桌面环境的Linux发行版。
    • Budgie,大多用Vala编程的Linux桌面环境。

    引用[编辑]

    1. ^ Vala· GitLab. GNOME. [16 March 2021]. (原始内容存档于2022-05-08). 
    2. ^ Vala Releases. Vala Project. [2021-03-18]. (原始内容存档于2022-03-08). 
    3. ^ Vala's Memory Management Explained. [2022-03-08]. (原始内容存档于2022-05-05). 
    4. ^ Projects/Vala/ReferenceHandling - GNOME Wiki!. wiki.gnome.org. [2023-01-18]. (原始内容存档于2022-05-05). 
    5. ^ Libgee on Gitlab. [2022-03-08]. (原始内容存档于2022-03-24). 
    6. ^ 6.0 6.1 Coding in Vala with Visual Studio Code. [2021-03-17]. (原始内容存档于2022-03-08). 
    7. ^ Coding in Vala with the Vim Text Editor. [2021-03-17]. (原始内容存档于2022-03-08). 
    8. ^ Enable Vala syntax highlighting and code browser support in GNU Emacs. [2021-03-17]. (原始内容存档于2021-05-12). 
    9. ^ 9.0 9.1 Vala Language Server, Vala, 2023-01-13 [2023-01-18], (原始内容存档于2022-09-25) 
    10. ^ esodan/gvls on GitLab. [2021-03-17]. (原始内容存档于2022-03-08). 
    11. ^ Vala Tools. [2021-03-29]. (原始内容存档于2022-01-06). 

    外部链接[编辑]