智能合約基礎語言(九)——Solidity繼承

智能合約基礎語言(九)——Solidity繼承

以太坊智能合約基礎語言(九):Solidity繼承?

www.liankuai.tech圖標

一.目錄

?繼承的概念

?繼承的參數傳遞

?重寫函數

?Solidity的繼承中的調用關係與多繼承

二.繼承的概念

Solidity語言為我們提供了繼承的支持,實現的方式是通過複製包括多態的代碼到子類來實現的。

繼承通過關鍵字is來實現,一起來看看下面的例子:

上面的例子中,合約Manager繼承了Person合約。

繼承的合約Manager可以訪問所有的非私有成員。包括internal的函數和狀態變數(這些是不能通過external的方式訪問的,如this.yourFunc()),我們來看下面的例子:

從上面的例子中,我們可以看到,子類可以訪問父類的public,internal許可權控制變數或函數,不能訪問private許可權控制的變數和函數。在子類中可以直接訪問狀態變數,原因是因為狀態變數默認是internal的。

三.繼承的參數傳遞

繼承支持傳參,繼承時可以有兩種方式傳參數到父類。下面來看第一種方式:

另外一種方式是類似修改器的語法,來直接看一個例子:

如果要傳入到基類的是簡單的常量,第一種方式會更加簡潔。但如果傳入的參數與子類的輸入參數有關,那麼你應該使用第二種方式,以獲取參數值。如果你同時使用了這兩種方式,後一種方式將最終生效。

四.重寫函數

在子類中允許重寫函數,但不允許重寫返回參數的類型,一起來看看下面的代碼:

上面代碼中的function data() returns(string){}將導致Override changes extended function signature報錯,因為不能修改返回的參數類型。

五.Solidity的繼承中的調用關係與多繼承

在繼承鏈中,由於繼承實現是代碼複製。如果出現函數重寫(類似其它語言的函數重載),最終使用的是繼承鏈上哪個合約定義的代碼呢?實際執行時,依據的是最遠繼承的原則(most derived)。下面來看一個例子:

上面的例子中,根據最遠繼承原則,大家可以想想MostDerived1,和MostDerived2中調用call()方法的運行結果。

實際上呢,MostDerived1,MostDerived2的call()將分別返回2和1。因為對於MostDerived1的最遠繼承合約是Base2,所以會使用其對應的函數,對於MostDerived2最遠的繼承者將是Base1。

5.1 指定調用父合約方法

雖然存在最遠繼承原則,但是我們仍可以在子合約中主動調用父合約被重寫的方法來觸發被覆蓋的函數。下面來看一個清理的例子:

5.2 super關鍵字

當我們在進行一些清理的時候,有些時候,我們希望繼承鏈條上每一個函數都能被調用以進行一些清理工作,這個時候,我們需要用到super關鍵字,繼續來看一個更多複雜的清理流程的代碼:

上面的例子中,在Final中調用kill(),將僅僅觸發Base2.kill()被調用,因為它是最遠繼承合約,從而跳過Base1.kill()。如果我們想也觸發Base1.kill(),解決方案是使用super。

在上面的代碼中,我們調用FinalWithSuper的kill()方法,將觸發按最遠繼承原則形成的鏈 Final,Base2,Base1,motal,owned的調用,上述代碼運行的事件如下:

這樣我們就實現了對鏈條上的所有方法的調用。另外,不知大家是否已經注意到,在使用super的上下文中,實際並不知道最終的調用鏈是如何的,還與繼承的關係有關。

5.3 多繼承與線性化

在Solidity中,允許多繼承,你可以同時繼承多個合約。實現多繼承的編程語言需要解決幾個問題,其中之一是菱形繼承問題又稱鑽石問題(假設我們有類B和類C,它們都繼承了相同的類A。另外我們還有類D,類D通過多重繼承機制繼承了類B和類C,因此D從理論上來講有兩份A的屬性和方法。因為上述圖表的形狀類似於鑽石(或者菱形),因此這個問題被形象地稱為鑽石問題(菱形繼承問題))。如下圖。

Solidity的解決方案是根據is後面的合約順序來線性化繼承關係,即overwrite的順序可以是,D < B < C < A, 也可以是 D < C < B < A。因此在D裡面只會有一個同名屬性或者函數的副本,而不會出現菱形問題的兩個副本並存的情況。 下面的代碼,Solidity會報錯Linearization of inheritance graph impossible。

原因是C會請求X來重寫A(因為繼承定義的順序是A,X),但A自身又是重寫X的,所以這是一個不可解決的矛盾。

一個簡單解決這種矛盾的原則是,總是指定基合約的繼承順序是從most base-like到most derived。總之, 按照既定的順序繼承就不會有問題, 先繼承祖父的再繼承父親。

本文完,獲取更多資訊,敬請關注區塊鏈工程師。

推薦閱讀:

TAG:語言 | 智能合約 |