-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DO NOT MERGE] Clean up inheritance specification. #3729
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -818,9 +818,9 @@ Additional Resources for Understanding Events | |
Inheritance | ||
*********** | ||
|
||
Solidity supports multiple inheritance by copying code including polymorphism. | ||
Solidity supports multiple inheritance including polymorphism. | ||
|
||
All function calls are virtual, which means that the most derived function | ||
All function calls (this includes external and internal calls) are virtual, which means that the most derived function | ||
is called, except when the contract name is explicitly given. | ||
|
||
When a contract inherits from multiple contracts, only a single | ||
|
@@ -831,11 +831,90 @@ The general inheritance system is very similar to | |
`Python's <https://docs.python.org/3/tutorial/classes.html#inheritance>`_, | ||
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 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: | ||
|
||
+---------------------+------------------------------+ | ||
| A function | ... can be overridden by a | | ||
| with visibility ... | function with visibility ... | | ||
+=====================+==============================+ | ||
| ``external`` | ``external`` or ``public`` | | ||
+---------------------+------------------------------+ | ||
| ``public`` | ``public`` | | ||
+---------------------+------------------------------+ | ||
| ``internal`` | ``internal`` or ``public`` | | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IGNORE, MY NOTE IS STUPID. Why not allow a contract with an internal function to be inherited by a contract that broadens that to public or external? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. internal functions can be overridden by a public function (this is stated here) but not by an external function, because an external function cannot be called internally. public = internal and external |
||
+---------------------+------------------------------+ | ||
| ``private`` | (none) | | ||
+---------------------+------------------------------+ | ||
|
||
+---------------------+---------------------------------+ | ||
| A function | ... can be overridden by a | | ||
| with mutability ... | function with mutability ... | | ||
+=====================+=================================+ | ||
| ``payable`` | ``payable`` | | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not yet clear about this rule. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A payable function should be able to be overridden by a function with mutability default, view or pure. You can this already today using boilerplate stubs, see: #3412 Also, this rule is assumed by ERC-721. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, that's probably right. @axic what do you think? |
||
+---------------------+---------------------------------+ | ||
| (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. | ||
|
||
An external function (but not a function of any other visibility) can be overridden by a public | ||
state variable. This means that the public state variable also needs the ``override`` keyword. | ||
|
||
Any other use of overriding between functions, modifiers, state variable or user-defined types | ||
(meaning overriding a function with a modifier or a state variable with a function, etc.) is disallowed. | ||
This means that you cannot declare a struct which has the same name as a function in super contract. | ||
|
||
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 multiple contracts in an inheritance hierarchy to have a member of the same name, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I fear this is not formal enough yet. |
||
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. | ||
|
||
Details are given in the following example. | ||
|
||
:: | ||
|
||
pragma solidity ^0.4.16; | ||
pragma solidity ^0.5.0; | ||
|
||
contract owned { | ||
function owned() { owner = msg.sender; } | ||
|
@@ -1116,13 +1195,13 @@ facilitating patterns like the `Template method <https://en.wikipedia.org/wiki/T | |
Interfaces | ||
********** | ||
|
||
Interfaces are similar to abstract contracts, but they cannot have any functions implemented. There are further restrictions: | ||
Interfaces are restrictions of abstract contracts in the following way: | ||
|
||
#. Cannot inherit other contracts or interfaces. | ||
#. Cannot define constructor. | ||
#. Cannot define variables. | ||
#. Cannot define structs. | ||
#. Cannot define enums. | ||
#. Interfaces cannot have implemented functions (only function declarations). | ||
#. Interfaces cannot inherit other contracts (but they can inherit interfaces). | ||
#. Interfaces cannot define a constructor. | ||
#. Interfaces cannot define variables. | ||
#. Functions in interfaces have to have ``external`` visibility. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
Some of these restrictions might be lifted in the future. | ||
|
||
|
@@ -1136,7 +1215,7 @@ Interfaces are denoted by their own keyword: | |
pragma solidity ^0.4.11; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please bump this version, because of |
||
|
||
interface Token { | ||
function transfer(address recipient, uint amount) public; | ||
function transfer(address recipient, uint amount) external; | ||
} | ||
|
||
Contracts can inherit interfaces as they would inherit other contracts. | ||
|
@@ -1163,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 | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public is more general than external, please list first to make a logical order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure? I would find it logical to list it in the external to internal order.