Subtyping

row type 是一种结构化类型, 也称静态鸭子类型.

如果类 A 中所有的 row 另一个类 B 全部都有, 那么我们称 A <: B.

和 A, B 是否是继承实现的完全没有关系, 无论 B 是传统的继承类型, 还是继承的原始类型, 还是匿名类型都成立.

说会继承, 生成子类型最常规的方法就是继承.

类继承分为实继承和虚继承

实继承可以带访问修饰符来决定成员变量的访问权限

举个例子, 如下继承关系

scala class K1(A, B) { } class K2(virtual A, public B) { };

编译期展开后为

```scala class K1 { private _a: A private _b: B }

class K2 { public b: B } ```

Method Resolve Order

你看这里出现了多继承多继承, 我们需要解析方法的调用顺序, 特别是菱形继承的情况下.

解析需要遵从三个原则 (Consistent)

满足这三个原则的算法就是 C3 线性化算法, 解析结果称为方法解析序(MRO, Method Resolution Order).

比如说这个图

scala class A(object) {} class B(object) {} class C(object) {} class D(object) {} class E(object) {} class K1(C, A, B) {} class K2(B, D, E) {} class K3(A, D) {} class Z(K1, K3, K2) {}

其 mro 应为 [Z, K1, C, K3, A, K2, B, D, E, object]

可以发现, mro 其实就是 row 这里面同名 row 的排列顺序.

Type Class

我们可以定义一些不参与 mro 排序的类, 这些类的 row 指针永远指向最上方.

```scala trait ToString { def tostring(self): str } class A: ToString { def tostring(self): str { "A" } } class B(A) { private b: B def tostring(self): str { "B" } }

// MRO = B, A typeof(B) = { B::tostring: (self) -> str, A::tostring: (self) -> str, }

let b = B();

B::tostring(b) // "B" ToString::tostring(b) // "B" A::to_string(b) // "A" ```

这里的 ToString 实质上就是起到了 type class 的效果.

等会儿, ToString::to_string 指向最上方返回 "B" 我能理解, 为什么还能调用 A::to_string 返回 "A" 呢?

这是因为 B 代理了 A 的指针, 在 scoped row type 系统里会自动转发.

如果要禁掉这种转发那就用虚继承即可.

这告诉我们, 还缺一套精确控制 row 转发的机制.

Method Resolve Qualifier

在类型层面, 简单起见, 我们把字段属性看成方法的一种, 我们不区分以下两者:

scala field: T field(): T

实继承的情况下, 方法可以有如下几种修饰词

来看一些例子, 我这里加上 123 的编号省的分不清, 实际上通过 & 附加的时候不带编号

scala type A = { inherit a1: str virtual a2: str // A::a 报错, a 是虚方法无法调用 } type B = { override b1: str final b2: str // B::b 报错, 禁止重写 final 方法 } type C = { override c1: str virtual c2: str // C::c 返回 c1 // C2::c 报错, c1 是虚方法无法调用 }

可以发现一虚皆虚, 编译期可以直接干掉虚方法后面的所有 row.