繼承(Inheritance)
繼承的本質(zhì):
繼承的實(shí)現(xiàn)方案是代碼拷貝施戴,所以合約繼承后壁榕,部署到網(wǎng)絡(luò)時(shí)慎恒,將變成一個(gè)合約任内。代碼將從父類拷貝到子類中。
繼承的定義
繼承使用is
融柬,一個(gè)合約可以繼承多個(gè)合約死嗦,用逗號(hào)分開(kāi)。
如果繼承的合約之間也有父子關(guān)系粒氧,那么合約要按照先父到子的順序排序越除。
比如:
contract X {}
contract A is X {}
contract C is X, A {} // 先X,再A
繼承的可見(jiàn)性
子合約不能訪問(wèn)父合約的private私有
成員
子合約可以訪問(wèn)父合約所有的非私有成員(包括internal
的函數(shù)和狀態(tài)變量)
父合約傳參
繼承的子合約外盯,必須提供父合約構(gòu)造方法需要的所有參數(shù)摘盆,有兩種方式實(shí)現(xiàn),如下:
contract Base {
uint x;
function Base(uint _x) { x = _x; }
}
contract Derived is Base(7) { //方式一
//方式二
function Derived(uint _y) Base(_y * _y) {
}
}
繼承中的重名
當(dāng)繼承多個(gè)合約時(shí)饱苟,這些父合約中不允許出現(xiàn)相同的函數(shù)名孩擂,事件名,修改器名箱熬,或互相重名类垦。
pragma solidity ^0.4.0;
contract Base1{
address owner;
modifier ownd(){
if(msg.sender == owner) _;
}
event dupEvent(address, bytes);
function dupFunc(){
dupEvent(msg.sender, msg.data);
}
}
contract Base2{
address owner;
modifier ownd(){
if(msg.sender == owner) _;
}
event dupEvent(address, bytes);
function dupFunc(){
dupEvent(msg.sender, msg.data);
}
}
//失敗狈邑,將會(huì)報(bào)錯(cuò) Identifier already declared
//contract DuplicateNames is Base1, Base2{}
contract DuplicateNames is Base1{}
還有一種比較隱蔽的情況,默認(rèn)狀態(tài)變量的getter函數(shù)導(dǎo)致的重名
重寫(xiě)
在子類中允許重寫(xiě)函數(shù)蚤认,但不允許重寫(xiě)返回參數(shù)簽名米苹,一起來(lái)看看下面的代碼:
contract Base{
function data() returns(uint){
return 1;
}
}
contract InheritOverride is Base{
function data(uint){}
function data() returns(uint){}
//Override changes extended function signature
//function data() returns(string){}
}
上面代碼中的function data() returns(string){}將導(dǎo)致Override changes extended function signature報(bào)錯(cuò),因?yàn)椴荒苄薷姆祷睾灻?/p>
抽象(Abstract Contracts)
抽象函數(shù)
是沒(méi)有函數(shù)體的函數(shù)
抽象合約
是包含了抽象函數(shù)
的合約砰琢,比如
contract Feline {
function utterance() returns (bytes32);
}
這樣的合約不能通過(guò)編譯蘸嘶,即使合約內(nèi)也包含一些正常的函數(shù)。但它們可以做為基合約被繼承陪汽。
接口
接口與抽象合約類似亏较,與之不同的是,接口內(nèi)沒(méi)有任何函數(shù)是已實(shí)現(xiàn)的掩缓,同時(shí)還有如下限制:
- 不能繼承其它合約雪情,或接口。
- 不能定義構(gòu)造器
- 不能定義變量
- 不能定義結(jié)構(gòu)體
- 不能定義枚舉類
其中的一些限制可能在未來(lái)放開(kāi)你辣。
接口基本上限制為合約ABI定義可以表示的內(nèi)容巡通,ABI和接口定義之間的轉(zhuǎn)換應(yīng)該是可能的,不會(huì)有任何信息丟失舍哄。
接口用自己的關(guān)鍵詞表示:
interface Token {
function transfer(address recipient, uint amount);
}
問(wèn)題
1.a繼承b宴凉,c繼承b,是不是一定要寫(xiě) constract c is a, b {}
2.下面的案例Final繼承的Base1和Base2有重復(fù)的kill函數(shù)表悬,沒(méi)有問(wèn)題嗎
3.下面的案例中弥锄,super.kill()和mortal.kill()有什么差別
pragma solidity ^0.4.0;
contract owned {
function owned() public { owner = msg.sender; }
address owner;
}
contract mortal is owned {
function kill() public {
if (msg.sender == owner) selfdestruct(owner);
}
}
contract Base1 is mortal {
function kill() public { /* do cleanup 1 */ super.kill(); }
}
contract Base2 is mortal {
function kill() public { /* do cleanup 2 */ super.kill(); }
}
contract Final is Base1, Base2 {
}