繼承和函式覆蓋:誰可以呼叫父函式?
我想知道在繼承的情況下誰仍然能夠呼叫原始覆蓋的函式。
假設我有以下設置:
contract A{ address public owner; function A(){ owner = msg.sender; } function doSomething(){ // does something } } contract B is A{ function doSomething(){ require(msg.sender == owner); // do something like A but restrict this function execution to owner super.doSomething(); } }
如果我部署契約
B
,一些不是所有者的外部帳戶仍然可以呼叫doSomething
父契約A
嗎?或者某些惡意合約是否會執行以下操作:contract EvilDoer{ function doSomethingEvil{ A contractB = A(addressOfdeployedB); contractB.doSomething(); } }
或者被覆蓋的函式是否被外部使用屏蔽了?
編輯:重載
也許對我和其他人來說詳細說明以下內容會很有趣和有幫助:在函式重載的情況下會發生什麼,即如果子類中的簽名與其父類不同(例如假設
function doSomething(uint256 someNumber){...}
在契約中B
)?
最後一個問題:重載概念適用於 Solidity,但對於其他支持重載函式的程式語言,即 C++,它們之間沒有任何關係。
同名但參數不同的函式由不同的簽名標識,因此它們實際上是不同的函式。如果
ContractA
定義doSomething()
、ContractB
定義doSomething(string myString)
和ContractB
繼承自ContractA
,最終 ContractB 將具有兩個使用者可以呼叫的有效函式:doSomething()
和doSomething(string myString)
。可見性也是簽名的一部分,但不能重載。現在的主要問題。從合約的外部,您不能呼叫已被覆蓋的基本函式。這是因為您從外部呼叫的是最終的合約實現,無論您如何定義客戶端上的介面來呼叫它。
如果你定義
contract EvilDoer{ function doSomethingEvil{ A contractB = A(addressOfdeployedB); contractB.doSomething(); } }
您只是在定義另一個 - 並且更具限制性 - 指向
ContractB
和指向doSomething()
. 它的實現是最後一個。但是,嘿,我知道預設函式可見性是公開的,如果我在
ContractA
as中明確定義基本函式external
怎麼辦?不多,因為您不能覆蓋更改其擴展簽名的函式。可見性和返回參數是擴展函式簽名的一部分,因此編譯器會拋出錯誤:
TypeError: Override changes extended function signature.
如果要編譯,則需要
external
在函式中也使用相同的修飾符ContractB
,然後再一次,函式的最後一個實現無論如何都會獲勝。請注意,更改可見性或返回參數也不被視為重載,因為函式由簽名標識,合約不能有兩個具有相同簽名和不同擴展屬性的函式。
有關繼承主題的更多資訊,您可以閱讀官方文件,特別是有關
super
關鍵字和合約最終繼承圖的資訊。