From 3339c6137dd3d1e435e9320a04dd532ad763e31f Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 15 Mar 2018 14:37:32 +0100 Subject: [PATCH] Inheritance. --- docs/contracts.rst | 85 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 26 deletions(-) diff --git a/docs/contracts.rst b/docs/contracts.rst index 95f5aa44c..d91de8d99 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -831,12 +831,45 @@ The general inheritance system is very similar to `Python's `_, especially concerning multiple inheritance. +Declaring two elements (for example functions) of the same name in +two different contracts that are part of the same inheritance hierarchy, +is called _overriding_. Declaring two elements of the same name in the +same contract is called _overloading_. + If a function is callable on a contract, it must also be callable in the derived contract. -This means that visibility and mutability of functions cannot be restricted, but it -can be extended. The visibility can change from external to public, but not from public +This means that visibility of functions cannot be restricted, but it +can be extended. Mutability in turn, can be restricted, but not extended. + +The visibility can change from external to public, but not from public to external or from external to internal. Functions that are marked ``view`` in the super contract, can be marked ``pure`` in the derived contract, but not the other -way around. +way around: + ++---------------------+------------------------------+ +| A function | ... can be overridden by a | +| with visibility ... | function with visibility ... | ++=====================+==============================+ +| ``external`` | ``external`` or ``public`` | ++---------------------+------------------------------+ +| ``public`` | ``public`` | ++---------------------+------------------------------+ +| ``internal`` | ``internal`` or ``public`` | ++---------------------+------------------------------+ +| ``private`` | (none) | ++---------------------+------------------------------+ + ++---------------------+---------------------------------+ +| A function | ... can be overridden by a | +| with mutability ... | function with mutability ... | ++=====================+=================================+ +| ``payable`` | ``payable`` | ++---------------------+---------------------------------+ +| (default) | (default), ``view`` or ``pure`` | ++---------------------+---------------------------------+ +| ``view`` | ``view`` or ``pure`` | ++---------------------+---------------------------------+ +| ``pure`` | ``pure`` | ++---------------------+---------------------------------+ If a function overrides a function from a super contract, it needs the ``override`` specifier, everything else is treated as an error. @@ -851,33 +884,37 @@ This means that you cannot declare a struct which has the same name as a functio Modifiers are treated in much the same way as functions: They use virtual lookup, require the ``override`` specifier, can use overloading and can have a missing implementation. -It is an error for two contracts in an inheritance hierarchy to have a member of the same name, -unless one member (``f_B``) is defined in a class (``B``) that derives (directly or indirectly) from the -class (``A``) the other member (``f_A``) is defined in; and: ``f_B`` uses the ``override`` keyword, ``f_A`` is a -function and ``f_B`` is either a function or a public state variable, both are compatible with -regards to visibility and state mutability as per the above rules and both have exactly the same -parameter and return types. +It is an error for multiple contracts in an inheritance hierarchy to have a member of the same name, +unless there is a single contract (``C``) which declares the member and all other contracts +that also declare the member inherit from it (directly or indirectly), all declarations +of that member except for the one in ``C`` use the ``override`` keyword, the members +are either all modifiers or all functions and potentially state variables, all inheritance +relations are compatible with +regards to visibility and state mutability as per the above rules and all have exactly the same +parameter and return types or, if there are functions or modifiers of the same name +declared in ``C`` with different parameters, then all of these functions or modifiers +have to be re-stated in all derived contracts that declare at least one of these +functions or modifiers. This in particular means that `private` members are not hidden from this mechanism and that overriding and overloading is incompatible. It also means that it is disallowed to inherit members of the same name that come from different base contracts unless they share a common base contract that defines the function to be overridden. +The above rule also means that it is illegal to inherit functions of the same name +from two base contracts who do not derive from the same base contract. It is only allowed +if there is a common base contract which also defines a function of this name. In that case, +the most derived contract can even override the function again. + As it is often useful to inherit the natspec comments for functions from super contracts. This has to be done explicitly using the ``@inherit`` natspec tag. This tag will inherit all properties that are not re-defined in the function of the derived contract. -TODO: - - - [ ] shall we make overriding and overloading work at the same time? - - [ ] shall we allow name clashes with private members? - - [ ] what about functions that have different return types? - Details are given in the following example. :: - pragma solidity ^0.4.16; + pragma solidity ^0.5.0; contract owned { function owned() { owner = msg.sender; } @@ -1205,17 +1242,13 @@ the state (i.e. if they are ``view`` or ``pure`` functions), because libraries are assumed to be stateless. In particular, it is not possible to destroy a library unless Solidity's type system is circumvented. -Libraries can be seen as implicit base contracts of the contracts that use them. -They will not be explicitly visible in the inheritance hierarchy, but calls -to library functions look just like calls to functions of explicit base -contracts (``L.f()`` if ``L`` is the name of the library). Furthermore, -``internal`` functions of libraries are visible in all contracts, just as -if the library were a base contract. Of course, calls to internal functions -use the internal calling convention, which means that all internal types +Library functions can use the ``inline`` keyword. Calling such functions +from another contract will not use ``DELEGATECALL``, but instead, +code of internal library functions and all functions called from therein +will at compile time be pulled into the calling +contract, and a regular ``JUMP`` call will be used. +This means that all internal types can be passed and memory types will be passed by reference and not copied. -To realize this in the EVM, code of internal library functions -and all functions called from therein will at compile time be pulled into the calling -contract, and a regular ``JUMP`` call will be used instead of a ``DELEGATECALL``. .. index:: using for, set