solidity支持多重继承,就不可避免地要面对棱形继承这种问题。solidity的解决方案与Python类似,使用C3 线性化来确定方法的调用顺序,也叫方法解析顺序(Method Resolution Order,MRO)
该算法过程如下:
如果继承至一个基类: class B(A) 这时B的mro序列为[B,A] 如果继承至多个基类 class B(A1,A2,A3 …) 这时B的mro序列 mro(B) = [B] + merge(mro(A1), mro(A2), mro(A3) …, [A1,A2,A3]) merge操作就是C3算法的核心。 遍历执行merge操作的序列,如果一个序列的第一个元素,是其他序列中的第一个元素,或不在其他序列出现,则从所有执行merge操作序列中删除这个元素,合并到当前的mro中。 merge操作后的序列,继续执行merge操作,直到merge操作的序列为空。 如果merge操作的序列无法为空,则说明不合法。
本文约定以下符号:
- L(A) : 类A的线性化结果的简写
- [B, C, D] : 某个类的线性化结果的具体值
- merge(…) merge 算法
- A->B,C:类A继承自B和C
利用以上符号,该算法归纳如下:
- 对于 A->B,C,D,则有 L(A) = [A] + merge(L(B), L©, L(D) , [B,C,D])
- 对于merge([X], [Y], [Z]),便利X序列的第一个元素,若该元素是其他序列中的第一个元素,或不在其他序列出现,则从所有序列中删除这个元素,合并到MRO中,继续遍历X的下一个元素;否则保留该元素,并依然继续遍历下一个元素。
- 直到merge操作的序列为空
我们以以下继承关系为例:
O
A -> O
B -> O
C -> O
K1 -> B, A
K2 -> C, A
Z -> K2, K1
求:L(Z)
根据MRO算法规则,
L(Z) = [Z] + merge(L(K2), L(K1), [K1, K2])
要想求L(Z),我们得先求出 L(K2) 与 L(K1),一直递归到L(O);
L(O) = [O]
L(A) = [A] + merge(L(O), [O])
= [A] + merge([O], [O])//遍历merge中的第一个序列的第一个元素O,该元素在第二个序列中位于首位,故将O合并到MRO,merge被清空。
= [A, O]
L(B) = [B, O]
L(C) = [C, O]
L(K1)= [K1] + merge(L(B), L(A), [B,A])
= [K1] + merge([B,O], [A,O], [B,A])//先处理B,符合条件,合并入MRO
= [K1, B] + merge([O], [A,O], [A])//再处理O,不符合条件,保留O,进而处理A,符合条件
= [K1, B, A] + merge([O], [O])
= [K1, B, A, O]
L(K2)= [K2, B, A, O]
有了计算L(K1)的过程,L(Z)也就迎刃而解了,有兴趣的同学可自行演算,答案是:
[Z, K2, C, K1, B, A, O]
回到上一篇博文的例子中:
contract Ancestor{
function Func(uint256 val)public pure returns(uint256){
return val;
}
}
contract BaseA is Ancestor{
function Func(uint256 val)public pure returns(uint256){
return Ancestor.Func(val * 2);
}
}
contract BaseB is Ancestor{
function Func(uint256 val)public pure returns(uint256){
return Ancestor.Func(val * 4);
}
}
contract Final is BaseA, BaseB {
}
调用Final.Func(N) 的结果是 4N,这里需要小心一点:solidity的is的实现与普通的有区别:Final is BaseA, BaseB 等效于 Final-> BaseB, BaseA
故
L(Final) = [Final] + merge([BaseB, Ancestor], [BaseA, Ancestor], [BAseB, BaseA])
= [Final, BaseB, BaseA, Ancestor]
所以调用Final.Func(N) 实际上是调用BaseB.Func(N)

本文探讨了在Solidity中如何处理多重继承带来的棱形继承问题,通过C3线性化算法确定方法调用顺序。算法过程包括合并线性化序列并递归计算,以确保MRO的正确性。举例说明了如何根据MRO计算特定类的线性化结果,并指出在Solidity中`is`关键字的特殊行为。
993

被折叠的 条评论
为什么被折叠?



