Dart / Flutter子类化以使用可选参数

时间:2019-05-15 16:42:01

标签: class dart flutter subclassing

我试图弄清楚如何创建一个类的子类而不指定父类的所有可选参数,但是仍然可以从子子类的构造方法访问它们。当使用无数属性将Flutter Widgets子类化时,这一点尤其重要。

例如 DoorWidget是具有许多可选参数的父类。

ChildDoorWidget继承了DoorWidget以添加额外的逻辑,但仍希望所有可选的父参数而不必在子类的super()方法中指定每个参数。

有什么办法吗?

这里是一个例子。

    // Maine widget
    class DoorWidget {
      String color = 'red';
      int width;
      int height;
      int p1;
      int p2;
      int p3;
      Function onKicked = () => print('Kicked');

      DoorWidget(this.color, {this.onKicked, this.width, this.height, this.p1, this.p2, this.p3});
    }

    class ChildDoorWidget extends DoorWidget {
      @override
      String color = 'green';
      ChildDoorWidget(String color, {Function onKicked, int width, int height})
          // Do I need to specify every parent optional parameter in the super class?
          // Is there a way to avoid this.
          : color = color,
            super(color, onKicked: onKicked, width: width);
    }

    main() {

      DoorWidget d = DoorWidget('green', width: 10, onKicked: () => print('DoorWidget Kicked') );
      print('Text Class');
      print(d.color);
      print(d.width);
      d.onKicked();

      ChildDoorWidget c = ChildDoorWidget('blue',
          width: 12, onKicked: () => print('ChildDoorWidget tapped called'));
      // Ideally I would like to do this:
      //  ChildDoorWidget m = ChildDoorWidget('blue', width: 12, onKicked: () => print('tapped called'), p1: 1, p2: 2, and any other optional params);
      print('\nMyText Class');
      print(c.color);
      print(c.width);
      c.onKicked();
    }

1 个答案:

答案 0 :(得分:1)

实际上,没有直接且简单的方法可以调用带有未定义参数的构造函数。

您想致电:

ChildDoorWidget m = ChildDoorWidget('blue', width: 12, 
                      onKicked: () => print('tapped called'),
                      p1: 1, p2: 2);

但由于 p1p2 未在 ChildDoorWidget 的构造函数中定义,您会收到错误“未定义命名参数。”

解决方法是记住 p1p2 可以通过 ChildDoorWidget 访问,并且使用级联表示法您仍然可以在调用构造函数的同一语句中设置它们的值:< /p>

ChildDoorWidget m = ChildDoorWidget('blue', width: 12, 
                      onKicked: () => print('tapped called'))
                      ..p1=1..p2=2;

除了必需的参数(本例中为 color)外,您可以对所有参数执行相同的操作

ChildDoorWidget m = ChildDoorWidget('blue')
                   ..width = 12
                   ..onKicked = (() => print('tapped called'))
                   ..p1 = 1
                   ..p2 = 2;

请记住,在执行级联赋值之前,构造函数的代码已完全执行。因此,请仅将此解决方法用于不使用其参数执行立即操作的构造函数,例如您的示例。

同样的逻辑可以应用于您关于在超类中指定父级可选参数的问题。

观察:coloronKickedDoorWidget 的初始化值是无用的,因为构造函数覆盖了这些值。这对 ChildDoorWidget 上的 color 有效。

以下是对上述实现的初始代码的修订:

void show(dynamic d) {
  print('\ncolor=${d.color}\nwidth=${d.width}\nheight=${d.height}\np1=${d.p1}\np2=${d.p2}\np3=${d.p3}\nonKicked=${d.onKicked}');
  d.onKicked == null ? '' : d.onKicked();
}

class DoorWidget {
  String color;
  int width;
  int height;
  int p1;
  int p2;
  int p3;
  Function onKicked;
  DoorWidget(this.color,
      {this.onKicked, this.width, this.height, this.p1, this.p2, this.p3});
}

class ChildDoorWidget extends DoorWidget {
  @override
  String color = 'orange'; //initialization useless because constructor overrides it with "this.color"

  ChildDoorWidget(String this.color) : super(color);
}

main() {
  print('\n\n\n create DoorWidget with color, width and onKicked');
  DoorWidget d = DoorWidget('green',
      width: 10, onKicked: () => print('DoorWidget Kicked'));
  show(d);

  print('\n\n\n create ChildDoorWidget with color, width and onKicked');
  ChildDoorWidget c = ChildDoorWidget('blue')
    ..width = 12
    ..onKicked = () => print('ChildDoorWidget tapped called');
  show(c);

  print('\n\n\n create ChildDoorWidget with many parameters');
  ChildDoorWidget m = ChildDoorWidget('yellow')
    ..width = 12
    ..onKicked = (() => print('tapped called'))
    ..p1 = 1
    ..p2 = 2;
  show(m);
}