<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 繼承(Inheritance) Solidity通過復制包括多態的代碼來支持多重繼承。 所有函數調用是`虛擬(virtual)`的,這意味著最遠的派生方式會被調用,除非明確指定了合約。 當一個合約從多個其它合約那里繼承,在區塊鏈上僅會創建一個合約,在父合約里的代碼會復制來形成繼承合約。 基本的繼承體系與`python`有些類似,特別是在處理多繼承上面。 下面用一個例子來詳細說明: ``` pragma solidity ^0.4.0; contract owned { function owned() { owner = msg.sender; } address owner; } // Use "is" to derive from another contract. Derived // contracts can access all non-private members including // internal functions and state variables. These cannot be // accessed externally via `this`, though. contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } } // These abstract contracts are only provided to make the // interface known to the compiler. Note the function // without body. If a contract does not implement all // functions it can only be used as an interface. contract Config { function lookup(uint id) returns (address adr); } contract NameReg { function register(bytes32 name); function unregister(); } // Multiple inheritance is possible. Note that "owned" is // also a base class of "mortal", yet there is only a single // instance of "owned" (as for virtual inheritance in C++). contract named is owned, mortal { function named(bytes32 name) { Config config = Config(0xd5f9d8d94886e70b06e474c3fb14fd43e2f23970); NameReg(config.lookup(1)).register(name); } // Functions can be overridden by another function with the same name and // the same number/types of inputs. If the overriding function has different // types of output parameters, that causes an error. // Both local and message-based function calls take these overrides // into account. function kill() { if (msg.sender == owner) { Config config = Config(0xd5f9d8d94886e70b06e474c3fb14fd43e2f23970); NameReg(config.lookup(1)).unregister(); // It is still possible to call a specific // overridden function. mortal.kill(); } } } // If a constructor takes an argument, it needs to be // provided in the header (or modifier-invocation-style at // the constructor of the derived contract (see below)). contract PriceFeed is owned, mortal, named("GoldFeed") { function updateInfo(uint newInfo) { if (msg.sender == owner) info = newInfo; } function get() constant returns(uint r) { return info; } uint info; } ``` 上面的例子的`named`合約的`kill()`方法中,我們調用了`motal.kill()`調用父合約的`銷毀函數(destruction)`。但這樣可能什么引發一些小問題。 ``` pragma solidity ^0.4.0; contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } } contract Base1 is mortal { function kill() { /* do cleanup 1 */ mortal.kill(); } } contract Base2 is mortal { function kill() { /* do cleanup 2 */ mortal.kill(); } } contract Final is Base1, Base2 { } ``` 對`Final.kill()`的調用只會調用`Base2.kill()`,因為派生重寫,會跳過`Base1.kill`,因為它根本就不知道有`Base1`。一個變通方法是使用`super`。 ``` pragma solidity ^0.4.0; contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } } contract Base1 is mortal { function kill() { /* do cleanup 1 */ super.kill(); } } contract Base2 is mortal { function kill() { /* do cleanup 2 */ super.kill(); } } contract Final is Base2, Base1 { } ``` 如果`Base1`調用了函數`super`,它不會簡單的調用基類的合約函數,它還會調用繼承關系圖譜上的下一個基類合約,所以會調用`Base2.kill()`。需要注意的最終的繼承圖譜將會是:Final,Base1,Base2,mortal,owned。使用super時會調用的實際函數在使用它的類的上下文中是未知的,盡管它的類型是已知的。這類似于普通虛函數查找`(ordinary virtual method lookup)` ## 基類構造器的方法(Arguments for Base Constructors) 派生的合約需要提供所有父合約需要的所有參數,所以用兩種方式來做,見下面的例子: ``` pragma solidity ^0.4.0; contract Base { uint x; function Base(uint _x) { x = _x; } } contract Derived is Base(7) { function Derived(uint _y) Base(_y * _y) { } } ``` 或者直接在繼承列表中使用`is Base(7)`,或像`修改器(modifier)`使用方式一樣,做為派生構造器定義頭的一部分`Base(_y * _y)`。第一種方式對于構造器是常量的情況比較方便,可以大概說明合約的行為。第二種方式適用于構造的參數值由派生合約的指定的情況。在上述兩種都用的情況下,第二種方式優先(一般情況只用其中一種方式就好了)。 ## 多繼承與線性化(Multiple Inheritance and Linearization) 實現多繼承的編程語言需要解決幾個問題,其中之一是`菱形繼承問題`又稱`鉆石問題`,如下圖。<br/> <img src="media/14825855458212/14826257952604.png" alt=""/> Solidity的解決方案參考`Python`,使用[C3_linearization](https://en.wikipedia.org/wiki/C3_linearization)來強制將基類合約轉換一個有向無環圖(DAG)的特定順序。結果是我們希望的單調性,但卻禁止了某些繼承行為。特別是基類合約在`is`后的順序非常重要。下面的代碼,Solidity會報錯`Linearization of inheritance graph impossible`。 ``` pragma solidity ^0.4.0; contract X {} contract A is X {} contract C is A, X {} ``` 原因是`C`會請求`X`來重寫`A`(因為繼承定義的順序是`A,X`),但`A`自身又是重寫`X`的,所以這是一個不可解決的矛盾。 一個簡單的指定基類合約的繼承順序原則是從`most base-like`到`most derived`。 ## 繼承有相同名字的不同類型成員 當繼承最終導致一個合約同時存在多個相同名字的修改器或函數,它將被視為一個錯誤。同新的如果事件與修改器重名,或者函數與事件重名都將產生錯誤。作為一個例外,狀態變量的`getter`可以覆蓋一個`public`的函數。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看