I have an abstract superclass with a factory that returns an instance of a subclass. Is it possible to have a method that is implemented only in superclass? In the following code, for instance, would it be possible to remove Wind::act()?
abstract class Element {
final String action; // what it does
String act() => action; // do it
factory Element() {
return new Wind();
}
}
class Wind implements Element {
final action = "blows";
act() => action; // Why is this necessary?
}
void main() {
print(new Element().act());
}
When removing Wind::act(), there is an error about it missing. Also, when extending rather than implementing the superclass, leaving out the subclass implementation doesn't cause an error. But with a factory method, extending is not an option.
To inherit functionality from Element
in Wind
, you need to either extend or mix-in Element
in Wind
. Merely implementing an interface will not inherit any implementation.
So, you need to have class Wind extends Element { ... }
.
That's not currently possible because Element
has no generative constructor that Wind
can use as super-constructor. So, you need to add that too, and make sure to initialize the action
field in that constructor.
class Element {
final String action;
Element._(this.action); // Generative constructor that Wind can use.
factory Element() = Wind; // Factory constructor creating a Wind.
String act() => action;
}
class Wind extends Element {
Wind() : super._("blows");
}
The generative constructor doesn't need to be private, but if you are declaring and using all the classes only inside your own library, it might as well be.
Another option is to have a separate ElementBase
class containing the action
field and act
function and an empty-named generative constructor. Mixins are not a good choice in this case, because there is no good way to make action
final when mixins can't have constructors.
abstract class Element {
String get action;
factory Element() = Wind;
String act();
}
class ElementBase implements Element {
final String action;
ElementBase(this.action);
String act() => action;
}
class Wind extends ElementBase {
Wind() : super("blow");
}
It's a common problem to want both a generative constructor for subclasses and a factory constructor generating the default implementation in an interface/skeleton class. The List
and Map
interfaces have this problem, and have solved it by exposing ListBase
and MapBase
. I think that is the best solution when you are exposing the superclass to other users in other libraries. If it's only used internally by yourself, I'll use the private/non-default-named generative constructor in the superclass.
来源:https://stackoverflow.com/questions/33664975/how-to-access-abstract-superclass-implementation-when-it-contains-a-factory-meth