如何使用工厂构造函数扩展抽象类?

问题描述 投票:0回答:2

情况如下:

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

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

class C extends A {
}

我有一个抽象类A。 B 类实现了 A。因此它重写了 doSomething() 方法。 C 类扩展了 A 类。

一切正常,直到我将工厂构造函数添加到 A 类中:

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

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

这会导致我的 IDE (IntelliJ IDEA) 出现错误:

预期的生成构造函数,但找到了工厂

我的第一个想法是为类 C 创建构造函数,我将在其中调用 A 的工厂构造函数。可以这样做吗?

当我尝试扩展 Exception 类时,我遇到了同样的问题。它还有一个工厂构造函数:

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

这就是为什么要创建自定义异常,我必须实现 Exception 类而不是扩展它,这真的让我很困惑。

我还想澄清一个术语问题。 我可以说从B类的角度来看,A是一个接口,所以B正在实现接口A。 但是,从 C 类的角度来看,A 是一个抽象类,因此 C 扩展了抽象类 A。这些说法正确吗?

谢谢你。

德米特里。

interface dart abstract-class
2个回答
17
投票

如果类没有构造函数,则会隐式添加生成构造函数。如果类具有显式构造函数,则不会添加生成构造函数。 你有两个选择。

  • 使工厂构造函数成为命名工厂构造函数并添加普通构造函数
abstract class A {
  void doSomething() => print('Do something..');
  factory A.name() => new B();
  A();
}
  • 或者命名普通构造函数并从扩展类中显式调用它
abstract class A {
  void doSomething() => print('Do something..');
  factory A() => new B();
  A.protected();
}

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

尝试DartPad

你的说法是对的。如果你实现一个类,它充当接口,如果你扩展它,它充当基类。


0
投票

我不知道它是否有效,但它解决了我的问题。我知道有很多解决方案可能是这个解决方案最糟糕的。 :) 但我想和你分享

有时后端 API 返回相同的模型,但值不同。 像这样。

Map<String,dynamic> map1 = {
  "version": "2.16.0",
  "language_1":"Dart",
  "framework_1":"Flutter",
};


Map<String,dynamic> map2 = {
  "version" : "10.0.1",
  "language_2":"javaScript",
  "framework_2":"NodeJs",
};

我需要

D
模型,因此可以从
D

扩展其他模型
class D{
  D({
    this.language,
    this.frameWork,
    this.version,
  });
  String? language;
  String? frameWork;
  String? version;
}

D

扩展模型
class A extends D{
  A();
  
  factory A.fromJson(Map<String,dynamic> json) => C.fromJsonForA(json);

}


class B extends D{
  B();
  
 factory B.fromJson(Map<String,dynamic> json) => C.fromJsonForB(json);
}

并在其他类中编写

factory
构造函数
C

class C extends D implements B,A{
  C({
    String? language,
    String? frameWork,
    String? version,
  }):super(
    language:language,
    frameWork:frameWork,
    version:version,
  );
  
  factory C.fromJsonForB(Map<String,dynamic> json){
    final c = C.protected(json);
    c.frameWork = json['framework_2'];
    c.language = json['language_2'];
    return c;
  }
  
  
  factory C.fromJsonForA(Map<String,dynamic> json){
    final c = C.protected(json);
    c.frameWork = json['framework_1'];
    c.language = json['language_1'];
    return c;
  }
  
  
  factory C.protected(Map<String,dynamic> json){
    return C(
      version: json["version"],
    );
  }
}

我用过:)

  A modelA = A.fromJson(map1);
  B modelB = B.fromJson(map2);
class Example {
  Example._();
  
  static printModel(D model){
    print("${model.language} : ${model.frameWork} version : ${model.version}");
  }
}

© www.soinside.com 2019 - 2024. All rights reserved.