面向对象
Z1h 语言支持面向对象, 并且支持多继承
声明
声明一个类有两种语言风格:
// map风格
class People {
name: 'zwr',
hi: e => print(`Hello, i am ${this.name}, you are ${e}`),
}
// 表达式风格
class Student {
name = 'zwr'
hi = e => print(`Hello, i am ${this.name}, you are ${e}`)
func bye(from) {
print(`Goodbye from ${from} to ${this.name}`)
}
}
请注意, 两种声明风格不能混用
初始化实例
以上文创建的两个类为例
// go风格
p = new(People)
// python风格
s = Student()
类变量
// 风格1
p.name = 'zq'
// 风格2
s['name'] = 'zq'
类函数
p.hi('tester')
构造函数
在声明类变量的时候, 声明init
函数即创建构造函数, 并且在继承关系中, 构造函数会从父类开始被调用, 顺序遵循 MRO
链的顺序.
建议通过map作为构造函数的参数
class A {
init = e => print(`通过参数${e}构造了一个A对象`)
}
class B (A) {
init: e => print(`通过参数${e}构造了一个B对象`),
}
A(123)
new(B, 456)
勾子函数
可以通过声明 setter
和 getter
函数来创建写/读的钩子, 在不需要经过勾子的地方, 需要改为调用 Store
和 Load
函数
// setter使用函数示例
class People {
age = 24
setter = (k, v) => {
if (k == 'age') {
this.Store(k, this.age + v)
} else {
panic('No key named ' + k)
}
}
}
p = new(People)
p.age = 100
print(p.age) // 124
p.name = 'zwr' // will panic
// getter使用函数示例
class Student {
age = 24
getter = (k, v) => {
if (k == 'age') {
var [age, has] = this.Load(k)
if (has) {
return age + ' Years'
} else {
return 'No age'
}
} else {
panic('Cannot take ' + k)
}
}
}
s = new(Student)
print(s.age)
del(s, 'age')
print(s.age)
print(s.name) // panic
请注意, Load函数有两个返回值, 一个是获取到的真实的值, 第二个是true/false, 表示是否存在这个key
如果直接在setter或getter内使用this.xxx, 大概率会导致死循环, 请注意用Store和Load替换
继承的情况下, 父类的setter和getter将不生效
继承
单继承
class People {
name = 'zwr'
}
class Student (People) {}
print(Student().name)
多继承
class AAA {
name = 'zwr'
}
class BBB {
age = 26
}
class CCC(AAA, BBB) {
hi = e => print(`My name is ${this.name}, age is ${this.age}`)
}
var c = CCC()
c.hi()
super
使用 this.super()
可以获取父类的引用, 以获取父类函数
class AAA {
hi = e=>print('Hi, i am AAA')
}
class BBB(AAA) {
hi = e=> {
print('Hi, i am BBB')
this.super().hi()
}
}
var b = BBB()
b.hi()
MRO
在多继承时, 免不了会出现优先级的冲突问题
使用 Object.mro(sth)
可以获得对象的MRO
链
class D() {}
class E() {}
class F() {}
class B(D, E) {}
class C(D, F) {}
class A(B, C) {}
Object.mro(A).map(e => e.Type())
// 可以看到, A类的MRO链是 [A, B, C, D, E, F, Object]
判断继承关系
class AAA {}
class BBB(AAA) {}
class CCC() {}
class DDD(BBB, CCC) {}
Object.isInstanceOf(BBB(), AAA) // true
Object.isInstanceOf(CCC(), AAA) // false
Object.isInstanceOf(DDD(), AAA) // true
BBB().InstanceOf(AAA) // true
CCC().InstanceOf(AAA) // false
DDD().InstanceOf(AAA) // true
强类型的类或对象
类或对象调用 SetStronglyTyped
函数, 类变量将不可以被修改类型, 或添加类变量
class People {age: 0}
People.SetStronglyTyped()
p1 = new(People)
p1.age = 20 // ok
p1.age = 'zwr' // panic
class Student {name = 'zwr'}
s1 = Student()
s2 = Student()
s1.SetStronglyTyped()
s1.name = 123 // panic
s2.name = 123 // ok
如果一个类是强类型的, 那么其衍生出来的子类和对象, 也都会是强类型的
如果需要取消强类型限制, 可以调用SetStronglyTyped(false)
协程(线程)安全的类或对象
类或对象调用 SetThreadSafe
函数, 类或变量将保证协程(线程)安全
class People {age: 0}
People.SetThreadSafe()
p = new(People)
print('Step 1:', p.age)
p.Lock()
print('Step 2:', p.age) // block
// wait
p.Unlock() // will print
如果一个类是协程安全的, 那么其衍生出来的子类和对象, 也都会是协程安全的
如果需要取消协程安全, 可以调用SetThreadSafe(false)
对象包含Lock、Unlock、RLock、RUnlock方法, 分别用于限制读和写操作, 可以手动调用函数以测试