面向对象

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)

勾子函数

可以通过声明 settergetter 函数来创建写/读的钩子, 在不需要经过勾子的地方, 需要改为调用 StoreLoad 函数 // 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方法, 分别用于限制读和写操作, 可以手动调用函数以测试