Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to extend an abstract class with factory constructor?

The situation is following:

abstract class A {
  void doSomething() => print('Do something..');
}

class B implements A {
  @override
  void doSomething() => print('Do something already..');
}

class C extends A {
}

I have an abstract class A. Class B implements A. Therefore it overrides doSomething() method. Class C extends A.

Everything works fine, until I'm adding factory constructor to class A:

abstract class A {
  factory A() => new B();

  void doSomething() => print('Do something..');
}

This leads to an error in my IDE (IntelliJ IDEA):

The generative constructor expected, but factory found

My first idea was to create constructor for class C where I would call factory constructor for A. Is it possible to do?

I got the same problem when I try to extend Exception class. It also has a factory constructor:

abstract class Exception {
  factory Exception([var message]) => new _ExceptionImplementation(message);
}

Thats why to create my custom exception I have to implement Exception class instead of extending it and it really confuses me.

I also would like to clarify one terminology question. Can I say that from point of view of B class, A is an interface, so B is implementing interface A. However, from point of view of C class, A is an abstract class so C is extending abstract class A. Are these statements correct?

Thank you.

Dmitry.

like image 778
Dmitry Papka Avatar asked Mar 29 '15 21:03

Dmitry Papka


1 Answers

If a class has no constructor a generative constructor is implicitly added. If a class has an explicit constructor no generative constructor is added. You have two options.

  • make the factory constructor a named factory constructor and add a normal constructor
abstract class A {
  void doSomething() => print('Do something..');
  factory A.name() => new B();
  A();
}
  • or make the normal constructor named and call it explicitly from the extending class
abstract class A {
  void doSomething() => print('Do something..');
  factory A() => new B();
  A.protected();
}

class C extends A {
  C() : super.protected();
}

try at DartPad

Your statement is right. If you implement a class it acts as an interface and if you extend it it acts as a base class.

like image 123
Günter Zöchbauer Avatar answered Sep 28 '22 03:09

Günter Zöchbauer