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). 

    外部連結[編輯]