当您可以使用一种方法进行大量分配时,为什么还要使用 setter?

Why use setter when you can assign massively using a method?

我发现我可以使用集合或方法将数据分配给 属性。

class Human {
  String name, address;
  
  set rewriteName(String name) {
    this.name = name;
  }
  
  set rewriteAddress(String address) {
    this.address = address;
  }
  
  void rewrite(String name, String address) {
    this.name = name;
    this.address = address;
  }
  
  String introduction() => "Name is $name. I live in $address";
  
  Human(this.name, this.address);
}

我尝试使用这两种方式分配一些数据,方法看起来比使用 setter 更有效,因为它只需要一次调用就可以改变一切:

Human human = Human('stacker', 'baghdad');

// using method
human.rewrite('overflow', 'new york');

// using setter
human.rewriteName = "Hooman";
human.rewriteAddress = "jakarta";

我的问题是为什么使用 setter 而不是方法?

它基本上是关于用法的样子,带有参数的方法调用与对 属性 的赋值。来自 Dart.dev 的 Effective Dart: Design

DO use setters for operations that conceptually change properties.

Linter rule: use_setters_to_change_properties

Deciding between a setter versus a method is similar to deciding between a getter versus a method. In both cases, the operation should be “field-like”.

For a setter, “field-like” means:

  • The operation takes a single argument and does not produce a result value.

  • The operation changes some state in the object.

  • The operation is idempotent. Calling the same setter twice with the same value should do nothing the second time as far as the caller is concerned. Internally, maybe you’ve got some cache invalidation or logging going on. That’s fine. But from the caller’s perspective, it appears that the second call does nothing.

在您的示例中,您正在比较一种更改两个属性的方法与两个单独的设置器。如果必须同时更新这两个属性(作为单个概念操作),则可以使用该方法。如果属性是独立的(并且满足上述条件),您可以改用 setter(如果您需要在设置它们时执行某些操作;否则,简单的数据字段可能更有意义)。

通常,getters 和 setter 的目标是私有的,因此不能从文件或库外部直接访问它们。

class Business {
  String name, _address;
  double lat, long;
  bool coordsCalculated = false;
  Map propertyRecords = {};
  
  get address {
    return _address;
  }
  
  set address(String address) {
    if (address == _address) return; // Nothing changed;
    _address = address;
    // API call to calculate lat/log
    APICall(onSuccess: (data) {
      lat = data.lat;
      long = data.long;
      coordsCalculated = true;
    });
  }
  
  void rewrite(String name, String address) {
    this.name = name;
    this.address = address;
  }
  
  String summary() {
    if (coordsCalculated) return "Business name is $name, here's a link to the map!";
    return "Business name is $name, at $_address.";
  }
  
  Human(this.name, String address) {
    this.address = address;
  }
}

class 的用户感觉他们使用的是普通的 属性,但它会做其他无声的事情。

方法也可以做到这一点,是的,但这会感觉更干净。

重要的是,getters 和 setter 不能是异步的,这肯定会给方法带来优势,但有很多有效的用途。

Getter 和 setter 在使用时也更易于阅读。少括号总是好事。

你当然不需要总是使用它们,或者当它们除了设置变量什么也不做时使用它们,但它们可能很好。

在我的一个小部件中,我有一个 getter 看起来像

FileState get fileState => FileUploaderKey.currentState!. widget.file.state;

这样阅读起来容易多了。它始终获取文件的当前状态,而

FileState fileState = FileUploaderKey.currentState!.widget.file.state;

只保存当前状态,不会随之改变。