Calling current class constructor from superclass method

27 views
Skip to first unread message

Guyren Howe

unread,
May 30, 2021, 4:32:04 PM5/30/21
to Dart Misc
I’m implementing a + operator in the superclass of a class hierarchy. The operator returns a new instance of the current class.

How can the superclass call the default constructor for its current subclass?

Bob Nystrom

unread,
Jun 1, 2021, 5:23:52 PM6/1/21
to General Dart Discussion
There is no built-in language support for this. If you control the superclass and subclasses, then you can handle it at the class level like:

abstract class Superclass {
  // Subclasses must override this and create instances of their own type.
  Superclass create();

  Superclass operator +(Superclass other) {
    var instance = create();
    // ...
    return instance;
  }
}

class Subclass extends Superclass {
  Superclass create() => Subclass();
}

If you want to be fancy with your types, you can use the CRTP:

abstract class Superclass<T> {
  // Subclasses must override this and create instances of their own type.
  T create();

  T operator +(Superclass other) {
    var instance = create();
    // ...
    return instance;
  }
}

class Subclass extends Superclass<Subclass> {
  Subclass create() => Subclass();
}

Cheers!

– bob

--
For more ways to connect visit https://dart.dev/community
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+uns...@dartlang.org.
To view this discussion on the web visit https://groups.google.com/a/dartlang.org/d/msgid/misc/96250404-D817-4496-A701-F9A708D753F4%40gmail.com.

Andrew Mezoni

unread,
Jun 2, 2021, 4:13:04 AM6/2/21
to Dart Misc, Bob Nystrom
Was this a question about the built-in capabilities of the language or about algorithms?

C# has an operator `default`.

var val = default(T);

Dart does not offer such a feature, because it is not a compile-time constant and reflection will be required.
Reflection is not universally used in Dart.
If your application is reflective, then this operator is easy to implement.

Or you can use builder for this. And generate code automatically. No problem.

среда, 2 июня 2021 г. в 02:23:52 UTC+5, Bob Nystrom:

Andrew Mezoni

unread,
Jun 2, 2021, 4:28:53 AM6/2/21
to Dart Misc, Andrew Mezoni, Bob Nystrom
void main() {
  final baz = Baz();
  baz.foo();
  final str = baz.default$.baz();
  print(str);
}

abstract class WithDefault<T> {
  T get default$;
}

abstract class Foo with WithDefault<Foo> {
  foo() {
    final value = default$;
    print(value.runtimeType);
  }
}

class Baz extends Foo {
  @override
  Baz get default$ => Baz();

  String baz() => 'baz';
}



среда, 2 июня 2021 г. в 13:13:04 UTC+5, Andrew Mezoni:

Andrew Mezoni

unread,
Jun 2, 2021, 4:48:53 AM6/2/21
to Dart Misc, Andrew Mezoni, Bob Nystrom
void main() {
  Default.add(() => Baz());
  final baz = Baz();
  baz.foo();
  final str = Default.get<Baz>().baz();
  print(str);
}

class Baz extends Foo {
  String baz() => 'baz';
}

class Default {
  static Map<Type, Function()> _ctors = {};

  static void add<T>(T Function() ctor) {
    if (_ctors.containsKey(T)) {
      throw ArgumentError.value(ctor, 'ctor', 'Duplicate value');
    }

    _ctors[T] = ctor;
  }

  static T get<T>() => getByType(T);

  static T getByType<T>(Type type) {
    final ctor = _ctors[type];
    if (ctor == null) {
      throw ArgumentError.value(type, 'type', 'Constructor not found');
    }

    return ctor() as T;
  }
}

abstract class Foo {
  foo() {
    final value = Default.getByType(runtimeType);
    print(value.runtimeType);
  }
}


среда, 2 июня 2021 г. в 13:28:53 UTC+5, Andrew Mezoni:
Reply all
Reply to author
Forward
0 new messages