3

サブクラスのインスタンスを返すファクトリを持つ抽象スーパークラスがあります。スーパークラスでのみ実装されるメソッドを持つことは可能ですか? たとえば、次のコードでは、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());
}

Wind::act() を削除すると、見つからないというエラーが発生します。また、スーパークラスを実装するのではなく拡張する場合、サブクラスの実装を省略してもエラーは発生しません。しかし、ファクトリ メソッドでは、拡張はオプションではありません。

4

1 に答える 1

4

から機能を継承するElementにはWind、 を拡張またはミックスインする必要がありElementますWind。インターフェイスを実装するだけでは、実装は継承されません。

だから、あなたが持っている必要がありますclass Wind extends Element { ... }。スーパーコンストラクターとして使用できるElement生成コンストラクターがないため、これは現在不可能です。したがって、それも追加する必要があり、そのコンストラクターでフィールドWindを必ず初期化してください。action

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");
}

ジェネレーティブ コンストラクターはプライベートである必要はありませんが、すべてのクラスを自分のライブラリ内でのみ宣言して使用する場合は、プライベートにすることもできます。

別のオプションは、フィールドと関数ElementBaseを含む別のクラスと、空の名前の生成コンストラクターを用意することです。この場合、Mixin は適切な選択ではありません。Mixin がコンストラクターを持つことができない場合、final にする良い方法がないからです。actionactaction

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");
}

サブクラスの生成コンストラクターと、インターフェイス/スケルトン クラスで既定の実装を生成するファクトリ コンストラクターの両方が必要になるのはよくある問題です。ListおよびインターフェースにはこのMap問題があり、 および を公開することで解決しましListBaseMapBase。スーパークラスを他のライブラリの他のユーザーに公開する場合は、これが最善の解決策だと思います。自分で内部的にのみ使用する場合は、スーパークラスでプライベート/デフォルト名のない生成コンストラクターを使用します。

于 2015-11-12T07:00:19.377 に答える