Dart初始化类字段“必须初始化不可为空的示例字段”

von4xj4u  于 2023-02-20  发布在  其他
关注(0)|答案(2)|浏览(195)

我是新来的 dart ,我正在学习 dart 课程。
我在理解Dart中的构造函数实际上是如何工作的方面遇到了一个问题。
在其他编程语言中,我习惯于以下面的方式初始化构造函数中的字段,但是在Dart中,我在使用下面的方式初始化字段时会收到许多警告和错误。

class Car {
  String brand;
  String model;
  int year;
   
   Car(String brand, String model, int year) {
      this.brand = brand;
      this.model = model;
      this.year = year;
   }
}

我认为这个问题与Dart中的null安全性有关,但我不想在声明字段时使用?操作符或关键字late
那么,谁能告诉我如何使用Dart中的构造函数正确地初始化字段?
谢谢

bxpogfeg

bxpogfeg1#

问题是构造函数体本质上只是一个函数,这意味着你可以做函数通常能做的任何事情,包括:

class Car {
  String brand;
  String model;
  int year;
   
  void printCarDetails() => print("This car is from $year");

  Car(String brand, String model, int year) {
    printCarDetails();  // <-- what should this print?
    this.brand = brand;
    this.model = model;
    this.year = year;   // <-- if [year] is only initialized here?
  }
}

问题是你可以在初始化字段之前使用它们(记住int不是默认的null--int?是),Dart需要在构造函数体之前有一个部分,这样你就可以保证你已经初始化了所有的东西,然后你就可以正常运行构造函数体了。
这一部分称为初始化列表:

class Car {
  String brand;
  String model;
  int year;

  Car(String brand, String model, int year) : 
    brand = brand,
    model = model,
    year = year
  {
    printCarDetails();
  }
    
  void printCarDetails() => print("This car is from $year");
}

所以:之后的所有内容都只是初始化字段,而{ }中的所有内容都是构造函数体,它可以访问这些字段。
但是初始化器列表看起来很难看,幸好Dart提供了一个简写,叫做初始化形参:

class Car {
  String brand;
  String model;
  int year;
  
  Car(this.brand, this.model, this.year) {
    // brand, model, and year are all initialized now
    printCarDetails();
  }

  void printCarDetails() => print("This car is from $year");
}

这是初始化字段的惯用方法,您应该尽可能坚持这种模式。
顺便说一句,在使用 super 类的构造函数时可能会遇到这个问题:

class Vehicle {
  String brand;
  Vehicle(this.brand);
}

class Car extends Vehicle {
  String model;

  // Passes [model] to the initializer list, and [numWheels] to Vehicle
  Car(this.model, super.numWheels);
}

这个特性被称为超参数,它是一个相对较新的特性。

ercv8c1e

ercv8c1e2#

示例字段必须在声明中有初始化器,使用初始化形参,或者在构造函数的初始化列表中初始化。下面是一些例子:

// initializer at the declaration
class Car {
  String brand = 'Brand';
  String model = 'Model';
  int year = 2023;

  Car();
}

// initializing formal
class Car {
  String brand;
  String model;
  int year;

  Car(this.brand, this.model, this.year);
}

// constructor's initialization list
class Car {
  String brand;
  String model;
  int year;

  Car(String brand, String model, int year)
      : this.brand = brand,
        this.model = model,
        this.year = year;
}

要了解更多信息以及更好地理解dart为什么以这种方式工作,请阅读官方文档。

相关问题