Vala

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

**描述**
Vala是一门编程语言，结合了脚本语言的高级编程语言建造时间性能，与低级的编程语言运行时间性能。相较于用C写成的应用和库，它致力于将现代编程语言特征带给GNOME开发者，而不用强加任何额外的运行时间要求，并且不用使用不同的ABI。Vala的语法类似于C#，并为了更好的适应GObject类型系统而做了修改。
Vala由Jürg Billeter构想，并由他和Raffaele Sandrini实现，他希望开发GNOME应用能有对C语言的更高级替代者。他们的确喜欢C#的语法和语义，但不想使用Mono，故而他们在2006年5月完成了一个编译器。最初它使用C来引导，一年后（在2007年7月的版本0.1.0发行中），Vala编译器实现了自举。

**版本历史**

**语言设计**

**特征**
Vala使用GLib和它的子模块（GObject、GModule、GThread、GIO）作为核心库，它们支持多数操作系统，并提供：平台无关线程、输入/输出、文件管理、网络套接字、插件、正则表达式等。Vala的语法目前支持如下现代语言特征：
*接口
*属性
*信号
*Foreach
*lambda表达式
*局部变量的类型推论
*泛型
*非空类型
*辅助内存管理
*异常处理
图形用户界面可以使用GTK部件工具箱和Glade GUI建造器来开发。

**内存管理**
对于内存管理，GType或GObject系统提供引用计数。在C语言中，编程者必须手工管理增加和移除引用，而在Vala中，管理这种引用计数是自动化的，如果编程者使用语言内建引用类型而非普通指针的话。唯一需要当心的是避免生成引用环，因为在这种情况下内存管理系统不能正确工作，此时需要使用Vala自带的week关键字标注弱引用解决。
对于不支持引用计数的类型，Vala也支持按照生命周期自动释放内存的非引用计数内存管理；Vala还可以通过指针手工内存管理。

**绑定**
Vala意图提供但现存C库的运行时间访问，特别是基于GObject的库，而不需要运行时绑定。要通过Vala使用一个由C语言编写的库，全部所需就是一个API文件（.vapi），包含采用Vala语法的类和方法声明。但是不支持C++库。目前在Vala的每次发行中，都包括了GTK以及大部份的GNU项目和GNOME平台的vapi文件。还有用Vala写的一个库叫做Gee，为常用数据结构提供基于GObject的接口和类。
为从用其他语言比如C#写的应用访问Vala库，写绑定生成器也应当是容易的，因为Vala解析器被写为一个库，所以所有运行时信息在生成一个绑定的时候都是可获得到的。

**工具**

**编辑器**
Vala的开发工具近些年来有了显着改进。下面是具有支持Vala编程的插件的一些流行IDE和文本编辑器：- GNOME Builder- Visual Studio Code，具有Vala插件- Vim，具有arrufat/vala.vim插件- Emacs，具有vala-mode- Atom - Geany- Kate

**代码智能**
目前，有两个活跃开发的语言服务器为Vala提供了代码智能：- vala-lang/vala-language-server，设计用于支持LSP的任何编辑器，包括VSCode、vim和GNOME Builder。- esodan/gvls，目前是Vala在GNOME Builder中的缺省语言服务器，它对支持LSP的任何编辑器提供支持。

**建造系统**
目前，有一些建造系统支持Vala，包括Automake、CMake、Meson等。

**调试**
对Vala程序的调试可以使用GDB或LLDB。对于IDE：- GNOME Builder拥有通过GDB的对Vala的内建调试支持。- Visual Studio Code拥有对GDB和LLDB的扩展，比如cpptools和CodeLLDB。

**示范代码**
一个简单的“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  ("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，用Vala写的邮件客户端。- elementary OS，具有大多用Vala编程的桌面环境的Linux发行版。- Budgie，大多用Vala编程的Linux桌面环境。

**引用**

**外部链接**
  The Vala Programming Languagedate=20120327191823 , on GNOME Live!
*Vala 语言书籍《Introducing Vala Programming》 （ Apress date=20191220092306  /  Amazon date=20220417125846 ）- 面向 Java 开发者的Vala 特性介绍 date=20220417130028 - 面向 C# 开发者的 Vala 特性介绍 date=20220417130131 -  Benchmark of Vala versus C# and Cdate=20120210040318 - Vala 语言编程规范（Geary版） date=20220417125856 
*Vala 的语言服务器（Language Server Protocol）项目：  VLS date=20210107234958 ，  GVLS date=20220308145226 
*Vala 语言社区：  The Vala community on GitHub date=20220417125846  - Vala 语言案例列表 date=20220417125849 - Vala 语言开发的数据库管理工具： DBKangaroo date=20201109060339 - Vala 语言库：官方库- Vala 语言库：第三方库 date=20220417130238