1

What is the correct approach to change the content of an inherited variable?
If contract A inherits contract B which has an variable b,
and contract A is initialising the inherited variable b through its constructor or one of its functions.
Should contract A then declare it as A.b = 123; or b = 123;

2 Answers 2

0

Both work. But I have never seen it used as A.b = 123;. I always use b = 123;.

1
  • Isn't there something to the concern, related to copying / assigning and memory management/gas costs?
    – NowsyMe
    Aug 12, 2018 at 22:03
0

Lots of things work. I would suggest a default style to help keeps things organized and untangled.

contract A is initializing the inherited variable b through its constructor

If you mean:

contract A is B {

  constructor() {
    b = something; // var inherited from A
  }
}

I would instead do:

contract B {

  bool public b;

  constructor() {
    b = true;
  }
}

contract A is B {

  ...
}

... because it keeps B's concerns wrapped in a complete module. B's constructor does run when A is deployed even it A has no constructor.

Security/Developer Error guards

In many cases the inherited variable is important. It is advisable to not rely on other developers knowing every nuance of the design and trusting them to avoid breaking something. Often, the inherited contract will expose state-changing functions and then disallow any direct writes to the variables. That way the possible state changes are limited to the intended use and the ways the state changes are clearly laid out.

You would get something like:

contract B {

  bool private b;

  constructor() {
    b = true
  }

  function _setB(bool newVal) internal {
    b = newVal;
  }

  function getB() public view returns(bool) { // because it's "private"
    return b;
  }
}

contract A is B {

  function setB(bool newVal) public onlyOwer {
    _setB(newVal);
  }

  // A will inherit the getB() function - replaces reliance on b being public
}

It's not apparent in the trivial example, but B would ensure that nothing bad happens to b - validation, coordinated updates of multiple variables, and so on. As the code base gets bigger, it is far easier to reason about the certainty of a private variable and a finite set of functions that can possibly change anything compared to considering the possibility of something undesirable lurking elsewhere in the code.

You can even pass arguments to inherited constructors if you need to. The compiler just needs a little guidance to map the inputs to each inherited constructor:

contract B {

  constructor(address user) {
  ...
}


contract C {

  constructor(bytes32 property, bool residential) {
  ...
}

contract A is B, C {

  constructor(address user, bytes32 property, bool residential) 
    B(user)
    C(property, residential)
  {
    // carry on
  }
}

In case it isn't clear, there is no need to explicitly mention the inherited constructors if they require no arguments. They run in any case.

Should contract A then declare it as A.b = 123; or b = 123

b is sufficient if the variable was inherited - public or internal visibility.

Hope it helps

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.