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

use*_*749 9 class subclassing dart flutter

我试图弄清楚如何在不指定父类的所有可选参数的情况下创建类的子类,但仍然可以从子类的构造函数访问它们。在继承具有无数属性的 Flutter 小部件时,这一点尤其重要。

例如,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();
    }
Run Code Online (Sandbox Code Playgroud)

小智 1

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

您想致电:

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

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

解决方法是记住,p1andp2可以通过级联表示法访问,ChildDoorWidget您仍然可以在调用构造函数的同一语句上设置它们的值:

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

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

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

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

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

color观察:和onKickedon 的初始化值DoorWidget是无用的,因为构造函数会覆盖这些值。color这对于ChildDoorWidget有效。

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

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);
}
Run Code Online (Sandbox Code Playgroud)