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 时,将调用派生终结器的正确版本。