2.20.

在 Daslang 中,类是旨在提供 OOP 功能的结构的扩展。 类提供单父继承、抽象和虚拟方法、初始值设定项和终结器。

基本的类声明类似于结构体的声明,但使用``class``关键字:

class Foo {
    x, y : int = 0
    def Foo {                           // 自定义初始化器
        Foo`set(self,1,1)
    }
    def set(X,Y:int) {                  // 内联方法
        x = X
        y = Y
    }
}

初始值设定项是名称与类的名称匹配的函数。 类可以有多个具有不同参数的初始化器:

class Foo {
    ...
    def Foo(T:int) {                    // 自定义初始化器
        self->set(T,T)
    }
    def Foo(X,Y:int) {                  // 自定义初始化器
        Foo`set(self,X,Y)
    }
}

终结器可以显式定义为名为 finalize 的 void 函数:

class Foo {
    ...
    def finalize {                      // 自定义终结器
        delFoo ++
    }
}

替代语法为:

class Foo {
    ...
    def operator delete {              // 自定义终结器
        delFoo ++
    }
}

不能保证隐式调用终结器 (参阅 Finalizers).

派生类需要使用 override 关键字显式地覆盖方法:

class Foo3D : Foo {
    z : int = 13
    def Foo3D {                         // 覆盖默认初始值设定项
        Foo`Foo(self)                   // 显式调用父类初始值设定项
        z = 3
    }
    def override set(X,Y:int) {         // 覆盖方法变量
        Foo`set(self,X,Y)               // 直接调用生成的方法函数
        z = 0
    }
}

类可以使用 abstract’ 关键字定义抽象方法:

class FooAbstract {
    def abstract set(X,Y:int) : void             // 内联方法
}

抽象函数需要是完全限定的,包括它们的返回类型。 类成员函数的推断方式与常规函数相同。

Sealed 函数不能被覆盖。``sealed``关键字用于防止覆盖:

class Foo3D : Foo {
    def sealed set(X,Y:int ) { // Foo3D 的子类不能再覆盖此方法
        xyz = X + Y
    }
}

不能从密封类继承。sealed 关键字用于防止继承:

class sealed Foo3D : Foo        // Foo3D 不能再继承自
    ...

名为 self 的指针在任何类方法中都可用。

可以通过 new 运算符创建类:

var f = new Foo()

局部类变量不安全:

unsafe {
    var f = Foo()       // 不安全
}

可以使用 -> 语法调用类方法:

f->set(1,2)

或者,使用 .运算符(在大多数情况下,除了一些宏):

f.set(1,2)

也可以显式调用该方法的特定版本:

Foo`set(*f,1,2)

类方法可以是常量:

class Foo {
    dir : float3
    def const length {
        return length(dir)  // dir 在这里是 const float3
    }
}

类方法可以是运算符:

class Foo {
    dir : float3
    def Foo ( x,y,z:float ) {
        dir = float3(x,y,z)
    }
    def Foo ( d:float3 ) {
        dir = d
    }
    def const operator . length {
        return length(dir)
    }
    def operator . length := ( value:float ) {
        dir = normalize(dir) * value
    }
    def const operator + ( other:Foo ) {
        return Foo(dir + other.dir)
    }
}

类字段可以声明为 static,即在类的所有实例之间共享:

class Foo {
    static count : int = 0
    def Foo {
        count ++
    }
    def finalize {
        count --
    }
}

类方法可以声明为 static。静态方法无权访问 self,但可以访问静态字段:

class Foo {
    static count : int = 0
    def static getCount : int {
        return count
    }
}

    let count = Foo`getCount()  // 他们可以在类外访问

2.20.1. 实现细节

类初始化器是通过使用 construct 语法添加本地 self 变量生成的。 该方法的主体以 with self 表达式为前缀。 最后一个表达式是 return <- self:

def Foo ( X:int const; Y:int const ) : Foo {
    var self:Foo <- Foo(uninitialized)
    with ( self ) {
        Foo`Foo(self,X,Y)
    }
    return <- self
}

类方法和终结器是通过提供额外的参数 self 生成的。 该方法的主体以 with self 表达式为前缀:

def Foo3D`set ( var self:Foo3D; X:int const; Y:int const ) {
    with ( self ) {
        Foo`set(self,X,Y)
        z = 0
    }
}

调用虚拟方法是通过 invoke 实现的:

invoke(f3d.set,cast<Foo> f3d,1,2)

每个基类都有一个 __rtti 指针和一个 __finalize 函数指针。 此外,还会为每个成员函数添加一个函数指针:

class Foo {
    __rtti : void? = typeinfo(rtti_classinfo type<Foo>)
    __finalize : function<(self:Foo):void> = @@_::Foo'__finalize
    x : int = 0
    y : int = 0
    set : function<(self:Foo;X:int const;Y:int const):void> = @@_::Foo`set
}

``__rtti``包含特定类实例的 rtti::TypeInfo。 rtti 模块中有辅助函数可以安全地访问 class_info:

def class_info ( cl ) : StructInfo const?

当为类指针调用 finalizer 时,将调用 finalize 指针。 这样,在基类指针上调用 delete 时,将调用派生终结器的正确版本。