跳到主要内容

类

Alia 语言支持面向对象编程,通过 class 关键字定义类。

1. 类的定义​

基本语法​

class <Key name> <Object body> ~ 类定义
class <Key name> extends <Key parent> <Object body> ~ 类继承
class <Key name> *[key: value, ...] ~ 可变类(体尾部 `...`)

示例:

class Person *[
name: ''
age: 0
new: alias <String name> <Number age> -> {
self.name = name
self.age = age
self
}
]

new 方法返回 self,即当前实例对象;实例化的结果由该返回值决定。

类表达式(匿名类)​

省略类名时,class *[body] 作为表达式求值,返回类体对象(匿名类),常配合 let/const 赋值使用:

const Greeter = class *[
name: String
new: alias <String n> -> {
self.name = n
self
}
greet: alias -> {
'Hello ' .. self.name
}
]

const g = new Greeter ['Alia']
print (call g.greet) ~ Hello Alia

可变性由类体尾部 ... 声明(不再使用 mut 修饰符):尾部带 ... 的类允许新增/删除实例属性,缺省则结构固定。

class Point *[
x: 0
y: 0
...
]
const p = new Point
p.x = 5
print p.x ~ 5
p.z = 1 ~ Point 为可变类,可新增属性

数组/对象字面量的尾部 ... 同样声明可变容器:

const nums = [0, 1, 2, ...] ~ 可变数组
const bag = *[a: 1, ...] ~ 可变对象
备注

mut {} / mut *{}(可变栈)语法不受影响,它与类型的可变性无关。

2. 类的实例化​

new 关键字实例化一个类,支持无参、数组参数与对象参数三种传参方式:

class Person *[
name: ''
age: 0
new: alias <String name> <Number age> -> {
self.name = name
self.age = age
self
}
]

const p1 = new Person ~ 无参实例化
const p2 = new Person ['Alice', 30] ~ 数组参数:按构造函数形参顺序传参
const p3 = new Person *[name: 'Alice', age: 30] ~ 对象参数:按构造函数形参名传参

对象式调用中,键名优先与构造函数形参名对应并转发;与形参名不匹配的键在构造完成后直接作为实例成员初始化。

类未定义 new 方法时启用默认构造:以类体全部成员(含继承链上的父类成员)初始化实例,实参数组按序号键('0'、'1'…)初始化,对象实参按键名初始化:

class Point *[x: 1, y: 2]

const p1 = new Point ~ { x: 1, y: 2 }
const p2 = new Point [3] ~ { x: 1, y: 2, '0': 3 }
const p3 = new Point *[x: 3] ~ { x: 3, y: 2 }

类体成员可声明类型注解,注解在运行时求值为 Null 且不生成字段初始化器,仅供类型检查与格式化消费。结构化形态与裸内置类型名均按注解处理:

class BigNum *[
digits: [Number, ...] ~ self.digits[i] 按 Number 检查,push 等变长操作可用
tag: Number | String
fallback: Number?
name: String ~ 裸内置类型名同样按注解处理
]

构造函数形参带关键字时,支持语法式调用,即按构造函数形参模式直接书写:

class Person *[
name: ''
age: 0
new: alias named <String name> aged <Number age> -> {
self.name = name
self.age = age
self
}
]

const alice = new Person named 'Alice' aged 30

实例化使用上述调用形式,不支持 new Person(...) 的函数式写法。

3. 类的成员访问​

点号 . 用于访问类的成员:

const person = *[ name: 'Alice', age: 30 ]
print person.name .. ' is ' .. person.age .. ' years old'

4. self 方法​

在类的方法中,self 指向当前实例对象,通过 self 访问实例自身。

class Counter *[
count: 0
increment: alias -> {
self.count += 1
self
}
getCount: alias -> {
self.count
}
]

const c = new Counter
call c.increment
call c.increment
print (call c.getCount) ~ 输出 2

零参方法以 call <Object>.<method> 调用。

5. 类的方法​

方法在类体中定义:

class Person *[
name: ''
age: 0
greet: alias -> {
'Hello, my name is ' .. self.name
}
new: alias <String name> <Number age> -> {
self.name = name
self.age = age
self
}
]

const person = new Person *[name: 'Bob', age: 25]
print (call person.greet)

6. 类的继承​

extends 关键字实现类继承:

class Person *[
name: ''
age: 0
greet: alias -> {
'Hello, my name is ' .. self.name
}
new: alias <String name> <Number age> -> {
self.name = name
self.age = age
self
}
]

class Student extends Person *[
studentId: ''
grade: 0
]

const student = new Student *[name: 'Charlie', age: 18]
student.studentId = '12345'
student.grade = 12
print student.name .. ' is a student with ID ' .. student.studentId

子类可以重写父类的方法:

class Person *[
name: ''
greet: alias -> {
'Hello, my name is ' .. self.name
}
new: alias <String toName> -> {
self.name = toName
self
}
]

class Student extends Person *[
studentId: ''
greet: alias -> {
'Hello, my name is ' .. self.name .. ', and my student ID is ' .. self.studentId
}
]

7. 类的构造函数​

构造函数通过 new 方法定义:

class Person *[
name: ''
age: 0
new: alias <String name> <Number age> -> {
self.name = name
self.age = age
self
}
]

const person = new Person *[name: 'David', age: 35]
print person.name .. ' is ' .. person.age .. ' years old'

构造函数委托(super.new)​

子类构造函数通过 super.new 调用父类构造函数,父构造执行后继续子类初始化:

class Parent *[
name: ''
new: alias <String n> -> {
self.name = n
self
}
]

class Child extends Parent *[
extra: ''
new: alias <String n> -> {
super.new n
self.extra = '!'
self
}
]

const child = new Child ['bob']
print child.name .. child.extra ~ 输出 bob!

8. super 方法​

super 在类方法与普通对象方法内部均可使用,用于调用父对象被覆盖的实现,self 保持绑定到当前实例。

class Animal *[
name: ''
speak: alias -> {
'animal:' .. self.name
}
new: alias <String n> -> {
self.name = n
self
}
]

class Dog extends Animal *[
speak: alias -> {
(call super.speak) .. ' (dog)'
}
]

const dog = new Dog ['Rex']
print (call dog.speak) ~ 输出 animal:Rex (dog)
  • self 绑定:父方法经 super 调用时,self 仍指向子实例,可访问子对象数据
  • 多级继承:三级及以上继承链中 super 逐级上溯,不会递归
  • Has super:(Has super) 在方法体内返回布尔值,判定接收者所属类型是否有父级;继承自父类且未被覆盖的方法同样返回 true
  • 不可枚举:super 不出现在 Object.keys 的结果中

9. 对象继承​

Alia 的继承不限于类,任何对象都可通过 extends 表达式继承,语法为 <Object> extends <Object>:

const base = *[
speak: alias -> {
'base-speak'
}
]
const dog = *[
speak: alias -> {
(call super.speak) .. '-dog'
}
] extends base

print (call dog.speak) ~ 输出 base-speak-dog

class X extends Y *[body] 与 *[body] extends Y 语义一致,类本质是“对象继承表达式 + 类型创建 + const 绑定”。

10. 示例代码​

10.1 基本类示例​

~ 基本类示例
class Person *[
name: ''
age: 0
greet: alias -> {
'Hello, my name is ' .. self.name
}
celebrateBirthday: alias -> {
self.age += 1
'Happy birthday! You are now ' .. self.age .. ' years old'
}
new: alias <String name> <Number age> -> {
self.name = name
self.age = age
self
}
]

const person = new Person *[name: 'Alice', age: 30]
print (call person.greet)
print (call person.celebrateBirthday)
print person.age

10.2 继承示例​

~ 继承示例
class Animal *[
name: ''
speak: alias -> {
'Animal sound'
}
new: alias <String name> -> {
self.name = name
self
}
]

class Dog extends Animal *[
breed: ''
speak: alias -> {
'Woof! Woof!'
}
]

class Cat extends Animal *[
breed: ''
speak: alias -> {
'Meow!'
}
]

const dog = new Dog *[name: 'Rex']
dog.breed = 'German Shepherd'
const cat = new Cat *[name: 'Whiskers']
cat.breed = 'Siamese'

print dog.name .. ' says ' .. (call dog.speak)
print cat.name .. ' says ' .. (call cat.speak)

10.3 复杂类示例​

~ 复杂类示例
class Rectangle *[
width: 0
height: 0
area: alias -> {
self.width * self.height
}
perimeter: alias -> {
2 * (self.width + self.height)
}
isSquare: alias -> {
self.width == self.height
}
new: alias <Number width> <Number height> -> {
self.width = width
self.height = height
self
}
]

class Circle *[
radius: 0
area: alias -> {
3.14159 * self.radius * self.radius
}
circumference: alias -> {
2 * 3.14159 * self.radius
}
new: alias <Number radius> -> {
self.radius = radius
self
}
]

const rect = new Rectangle *[width: 5, height: 10]
print 'Rectangle area: ' .. (call rect.area)
print 'Rectangle perimeter: ' .. (call rect.perimeter)
print 'Is square: ' .. (call rect.isSquare)

const circle = new Circle *[radius: 7]
print 'Circle area: ' .. (call circle.area)
print 'Circle circumference: ' .. (call circle.circumference)

11. 类与类型系统​

Alia 默认启用静态类型系统,类型检查在 Check 阶段执行,位于 Astify 之后、Interpret/Compile 之前。类定义中可添加类型注解:

class Person *[
name: String = ''
age: Number = 0
new: alias <String name> <Number age> -> {
self.name = name
self.age = age
self
}
]

const person: Person = new Person *[name: 'Alice', age: 30]

12. 类的静态成员​

类定义中可添加静态成员:

class MathUtils *[
static PI: 3.14159
static E: 2.71828
square: alias <Number num> -> {
num * num
}
cube: alias <Number num> -> {
num * num * num
}
]

print 'PI: ' .. MathUtils.PI
print 'E: ' .. MathUtils.E
print 'Square of 5: ' .. (MathUtils.square 5)
print 'Cube of 3: ' .. (MathUtils.cube 3)

带参数的成员方法以 (<Object>.<method> <args>) 形式在表达式中调用,零参成员方法以 call <Object>.<method> 调用。

下一步​