首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用NullSafety实现颤动中的单例类

用NullSafety实现颤动中的单例类
EN

Stack Overflow用户
提问于 2021-03-07 04:12:46
回答 4查看 4.4K关注 0票数 7

我有这样一个类,它通过使用工厂构造函数来获取一些参数,如果instance为null,将创建一个新对象;如果不为null,则将返回instance的值,因此我们总是收到相同的对象(Singleton)。这就是我在启用dart的空安全特性之前使用单例模式的方式。

代码语言:javascript
复制
class GuestUser extends User {
  static GeustUser _instance;


  factory GuestUser(
      {required String firstName,
      required String lastName,
      required String email,
      required Address address,
      required PaymentInfo paymentInfo}) {
    if (_instance == null) {
      _instance =
          GuestUser._(firstName, lastName, email, address, paymentInfo);
    }
    return _instance;
  }

现在启用了null-safety,我得到了这个错误:

代码语言:javascript
复制
The non-nullable variable '_instance' must be initialized.
Try adding an initializer expression.

此外,不再需要if (_instance == null)

如果我像这样定义_instancestatic late final GuestUser _instance;,那么我就不能只在需要时使用if (_instance == null)来创建_instance。因此,我必须删除if语句,并在每次调用工厂构造函数时创建一个新实例。

如何解决这个问题并创建一个启用了null-safety的单例类?

我在脑海中有一个解决方案,用一个布尔变量来跟踪实例:

代码语言:javascript
复制
static late final GeustUser _instance;
static bool _isInstanceCreated = false;

  factory GuestUser(
      {required String firstName,
      required String lastName,
      required String email,
      required Address address,
      required PaymentInfo paymentInfo}) {
    if (_isInstanceCreated == false) {
      _instance =
          GuestUser._(firstName, lastName, email, address, paymentInfo);
    }
    _isInsanceCreated = true;
    return _instance;
  }

但是我想知道是否有一种方法可以在不定义新变量的情况下,通过使用null-safety的特性来实现这一点。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2021-03-07 04:30:37

你的单例有点奇怪,因为你接受的参数只会在第一次被调用时使用。这不是一个很好的模式,因为如果你想为两个不同的访客用户使用它,它会给你带来一些惊喜。

在您的示例中,只使用GuestUser?作为_instance的类型是有意义的。在Dart中,默认情况下不可为空的情况不应该被视为null的糟糕用法,您应该明确地在有意义的地方使用null (特别是如果我们可以防止引入bool变量来指示是否设置了变量的话)。在您的示例中,_instance在第一次初始化之前为null。

我们使用??=运算符的示例。操作符将检查_instance是否为null,如果是null,它将把变量赋给通过调用构造函数GuestUser._创建的对象。此后,它将返回_instance的值。如果_instance已经有一个值(不是null),那么这个值将不会调用GuestUser._构造函数而直接返回。

代码语言:javascript
复制
class GuestUser extends User {
  static GuestUser? _instance;

  factory GuestUser(
          {required String firstName,
          required String lastName,
          required String email,
          required Address address,
          required PaymentInfo paymentInfo}) =>
      _instance ??=
          GuestUser._(firstName, lastName, email, address, paymentInfo);
}

如果您有一个更传统的单例,您可以在定义中创建实例的位置创建一个static final变量。但这不允许参数。

票数 3
EN

Stack Overflow用户

发布于 2021-05-18 21:54:42

正如@julemand101提到的,你的单例实际上很奇怪,因为通常你会这样做:

代码语言:javascript
复制
class Foo {
  static final instance = Foo._();
  Foo._();
}

但是,您不能使用参数实例化它。为此,您可以执行以下操作:

代码语言:javascript
复制
class Bar {
  static Bar? instance;
  Bar._(int i);

  factory Bar.fromInt(int i) {
    var bar = Bar._(i);
    instance = bar;
    return bar;
  }

  void display() => print('Bar instance');
}

void main() {
  final nullableBar = Bar.instance;
  final nonNullableBar = Bar.fromInt(0);

  nullableBar!.display(); // Runtime error as Bar.instance is used before Bar.fromMap(0)
  nonNullableBar.display(); // No error
}
票数 2
EN

Stack Overflow用户

发布于 2021-06-09 17:52:11

您可以使用相同的传统方法来创建单例。您只需将空安全操作符放在正确的位置。

代码语言:javascript
复制
class MySingleton {
  // make this nullable by adding '?'
  static MySingleton? _instance;

  MySingleton._() {
    // initialization and stuff
  }

  factory MySingleton() {
    if (_instance == null) {
      _instance = new MySingleton._();
    }
    // since you are sure you will return non-null value, add '!' operator
    return _instance!;
  }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66510201

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档