0

Is it possible to call a second ancestor method in dart? something like super.super.hello()? If it's possible, how can it be written?

class A {
  void hello() {
    print('A');
  }
}

class B extends A {
  @override
  void hello() {
    print('B');
  }
}

class C extends B {
  @override
  void hello() {
    // How to call the hello() implemented in the class A here?
  }
}

void main() {
  var c = C();
  c.hello();
}
Chris
  • 143
  • 2
  • 12
  • As far as I know, this is not possible in Dart. – julemand101 May 05 '21 at 14:46
  • 1
    I hope there isn't, ever. That would be a nightmare to debug and refactor. – Randal Schwartz May 05 '21 at 14:46
  • 1
    The accepted answer on https://stackoverflow.com/questions/586363/why-is-super-super-method-not-allowed-in-java gives more context as to why this is the case. The answer is for java, but the principles are the same. – Stephen May 05 '21 at 15:55

1 Answers1

2

It's not possible.

The reason it's not possible is that it breaks abstraction. When you look at class C extend B, all you need to know about B is which signatures its members has and which interfaces it implements. As long as that stays effectively the same, your valid code will keep working.

Consider what would happen if the author of B decided to make themselves a helper base-class:

abstract class _BaseB extends A {
  String get _myName;
  @override
  void hello() {
    print(_myName);
  }
}
class B extends _BaseB {
  @override
  String get _myName => "B";
}

That's a perfectly valid refactoring. The resulting class B has all the same members and implements all the same interfaces (and also _BaseB, but it's private so nobody can see that).

The C class above would keep working if all it does is to call super.hello(). If it had a way to ask for super.super.hello(), that might no longer be valid.

Similarly if the B class was changed to:

class B implements A {
  @override 
  void hello() {
    print("B");
  }
}

(changing extends to implements), then all methods of B works the same as before and it implements the same interfaces. Again, there is no visible differences to the users of the B class. But if you could call something like A.super.hello() to reach the A class's hello method, then that would now break because that method isn't in the B class at all.

So, by restricting super.hello() to only call methods on the precise class you write as the superclass, you are prevented from introducing dependencies on the implementation of B, dependencies which would make otherwise valid refactorings into breaking changes.

lrn
  • 64,680
  • 7
  • 105
  • 121