Solidity

繼承和函式覆蓋:誰可以呼叫父函式?

  • September 6, 2017

我想知道在繼承的情況下誰仍然能夠呼叫原始覆蓋的函式。

假設我有以下設置:

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(). 它的實現是最後一個。

但是,嘿,我知道預設函式可見性是公開的,如果我在ContractAas中明確定義基本函式external怎麼辦?

不多,因為您不能覆蓋更改其擴展簽名的函式。可見性和返回參數是擴展函式簽名的一部分,因此編譯器會拋出錯誤:

TypeError: Override changes extended function signature.

如果要編譯,則需要external在函式中也使用相同的修飾符ContractB,然後再一次,函式的最後一個實現無論如何都會獲勝。

請注意,更改可見性或返回參數也不被視為重載,因為函式由簽名標識,合約不能有兩個具有相同簽名和不同擴展屬性的函式。

有關繼承主題的更多資訊,您可以閱讀官方文件,特別是有關super關鍵字和合約最終繼承圖的資訊。

引用自:https://ethereum.stackexchange.com/questions/25046