shawind 发表于 2010-1-23 12:43:11

Genie-01-数据类型

###数值类型:
bool //布尔类型,值是true或false,只须要1位的空间
char uchar //8位整数或字符
unichar //16位字符
int uint //32位整数
long ulong //64位整数
float double //32位和64位浮点数

###简单的引用类型:
string //utf-8的字符串
array //数组

###高级引用类型
dict //字典
list //列表

dict list这两个类型需要gee的支持。编译时还要用--pkg指定库。
用于mingw32的gee库在http://code.google.com/p/valide/downloads/list可以下到
把里面的三个目录直接拖到c:\vala-0.7.9\中,然后复制压缩包里的share\vala\vapi\gee-1.0.vapi文件到默认的vapi目录下。我的系统是win7,所以这个目录在c:\ProgramData\vala\vapi\
也可以为valac编译器直接指定vapi目录,让它自己去找,
如valac --vapidir=..\share\vala\vapi --pkg gee-1.0 test.gs

###其他类型
delegate //委托
namespace //命名空间
enum //枚举
struct //结构体

###不知道算不算类型的部分,官网是把它放到类型里说的
可空类型
弱引用
传递所有权
指针

###类

=================================================================================

###声明变量有两种方式。
都需要在声明的时候初始化值,或者在声明后,最少赋一次值,不然就报错。
这里有点麻烦,就不能创建时默认初始化么?
1.直接用类型标识

i:int = 5
s:string = "test"
d:double = 3.14
...

2.可以用类型推导的方式

var i = 5
var s = "test"
var d = 3.14
...

另外var还可以同时声明多行多个变量

var
    i = 5
    s = "test"
    d = 3.14
    ...


###string类型

init
    s:string = "test"
    print s

实际上,genie编译成c代码时是用char*来处理字符串的。也就是说字符串的最后是以0结尾。glib里提供了很多字符串操作。而且如果使用posix库的话,依然可以继续使用c的字符串操作函数,另外还有中文处理...这是个大坑,下次再填吧。

###array类型

init
    a:array of string = {"a", "b", "c"}
    print "%d", a.length //获得数组长度

array of string看起来有点怪怪的。不过读起来却很流畅,有点像自然语言一样,不知道是长处还短处了。
array是说数组类型本身,of后面的string是指数组里元素的类型。
实际上编译成c后,array of string是用char**来工作的。
这种声明时还是要手动初始化,不然报错。面倒。强烈希望以后的新版本能自动初始化。
当然也可以在声明中指定数组的大小

init
    a:array of string = {"a", "b", "c"}
    print a
    print a
    print a

还可以利用var,用面向对象的方式来声明,这种声明方式就必须指定数组大小。可能是编译器不知道要new多大的空间出来吧。终于可以不用手动初始化了。

init
    var a = new array of int
    print a

数组可以用const来修饰,定义成常量数组

###dict字典类型,这东西其实就是关系数组或hash表。

init
    var d = new dict of string,int
    d["Tom"] = 20
    d.set("Joe", 30)
   
    print "%d", d["Tom"]
    print "%d", d["Joe"]

在of后面跟两个类型就搞定了,可以自动初始化。
d.get_keys()和d.get_values()可以得key和value的数组

###list列表类型

init
    var l = new list of int
    l.add(1)   
    l.add(2)
    print l

也没什么好说的,完全可以当数组操作。

###delegate 委托

delegate dg(a:int):bool
   
def func(a:int):bool
    print "%d", a
    return true

def invoke(d:dg, a:int):bool
    var r = d(a)
    return r

init
    if invoke(func,100) is true
      print "OK!"
    else
      print "Failed!"

定义的方法还是比较简单的,可以把定义好的委托直接当一种类型使用。

###namespace命名空间
其实我一直觉得用文件结构来构成包模块什么的是最直观的方式,可惜的是Genie里是用的c++,c#那种方式的。
使用一个命名空间用uses,可以多行

uses
    Posix
    Gtk

自己弄命名空间的话

namespace Name1
    def say(s:string)
      print "Name1:" + s

    namespace Name2
      def say(s:string)
            print "Name2:" + s

init
    Name1.say("hello!")
    Name1.Name2.say("hello!")


###enum枚举类型

enum test
    a
    b
    c

init
    print "%d", test.a
    print "%d", test.b
    print "%d", test.c

如果不手动指定值的话,会自动从0开始,依次往后递增1。
像这个例子中,a=0,后面的b=1,c=2。如果手动指定a=5,那么后面的bc会自动调整为b=6,c=7。

###struct结构体

struct human
    name:string
    age:int

init
    s:human = {"Tom", 20}
    print ("%s\n%d", s.name, s.age)

声明后,就能拿来当新类型使用,但遗憾的是不能像d那样往struct里添加方法了。

###可空类型
因为在默认情况下,Genie保证所有的引用点都必须有实际对象,所以就不能为变量赋空值。在声明变量的类型标识后面加上个?号,就可表示这个变量可以为空。

def func(param:string?):string?
    return param

init
    print func(null)

实在不太明白这个功能有什么大用处...
有趣的是,官网里的例子还写成了string? param,c方式的声明,根本无法通过编译。
可见这个功能就连他们自己也没怎么用吧。哈哈~

###弱引用
实在不太清楚这是干什么用的。如果是指绕开编译器自己的内存管理,用不从object继承的class不就行了?
先坑在这里吧。

###传递所有权
和C获取指针用*一样,这个操作用#

init
    var s = "a"
    t:string = #s
    print t

在这个操作里,t获得s里的值,而s会被清空。还是不明白这是干什么用的...
试了下int类型,不能用#,编译错误。array可以拿到值,不过原来的数组,也就是指针,被彻底清掉了。
list等类型也是差不多的情况。看来#只能用在引用类型。

###指针
主要是Genie用来手动管理内存用的。

class Human
    prop name:string

    def input_name(n:string)
      name = n

init
    tom:Human* = new Human
    tom->input_name("Tom")
    print tom->name
    delete tom

在类型后加个*用来创建其指针
和c++一样,用->来访问类指针中的成员和对象了...
显式的new和delete

###类
Genie中的类的所有成员变量,没有用_或private修饰的话,默认是公开的。
比如上面的那个Human类,编译器自动为成员变量name加上了公开的set_name,get_name方法来读写它。
声明成员变量要用prop来修饰。
创建实例用new
可以包含:
1.init语句块用来初始化类,但不可以加参数,这个语句块依赖GLib.Object,如果类不从Object继承,则不可以用init语句块,final和construct没有这个限制。
2.final语句块用来销毁类,同样不可以加参数。
3.construct语句块被用来构建类,但只限于操作类自己的成员变量,因为有init块来干别的事情。可以有多个初始化方法。如果不写,编译器会自动创建一个无参的。

class Human:Object

    prop name:string

    init
      print "Human is inititialized"

    final
      print "Human is being destroyed"

    construct(n:string)
      name = n

    construct default()
      name = "noname"

    def input_name(n:string)
      name = n

init
    tom:Human = new Human("Tom")
    joe:Human = new Human.default()
    print tom.name
    print joe.name

类成员和方法的修饰
private私有,和_开头一个效果
abstract 抽象,自己没有实现,但所有子类必须实现这个方法
extern 外部的,可以是定义在c(asm)源文件中的方法,c文件最后一起编译
inline 内联,对于非常小的方法,可以提升性能
virtual 虚拟,可在子方法中重写
override 重写,覆盖父类的同名虚拟方法
static 静态,无须类实例的方法

从Object继承来的类都支持event的写法,这个用起来非常简单
现版本下,不支持带返回值的回调,以及所有的事件永远不能私有。

class Button : Object
    event click()

init
    var b = new Button()
    b.click += def(t)
      print "001"
    b.click += def(t)
      print "002"
    b.click()


Genie的接口可以带成员变量,接口也可以从接口继承。

interface ITest
    prop abstract data:int
    def abstract fn()

class CTest : Object implements ITest
    prop data:int
    def fn()
      print "fn"

init
    var t = new CTest()
    t.fn()

用类实现接口时,可以从多个接口继承
如:class ListClass : Object implements Collection,List

###判断类型
用isa可以判断出变量的类型,很简单,一看就明了。

init
    var o = new list of string
    if o isa Object do print "a list of string is an object"
    if o isa list of Object do print "a list of string is a list of Object"
    if o isa Gee.Iterable    do print "a list of string implements Iterable"


还有不少自己都不能理解的。不过,这部分看起来用处不大的样子。
基本上还是比较容易的。自我感觉,一周之内初步掌握Genie,应该没有什么问题。
难道这就是Genie的官方文档非常之少的理由么?
页: [1]
查看完整版本: Genie-01-数据类型