如何在Dart中声明final类以防止从它扩展?

tkqqtvp1  于 2023-02-17  发布在  其他
关注(0)|答案(3)|浏览(237)

在Java\Kotlin中,我们有一个String类,它是final且不可变的。
我试图用final关键字标记类,但看起来不允许。
所以,我有点困惑,如何在Dart中声明final类?
注意:情况是-我想在外部示例化这个类,但是禁止扩展它。所以使用私有构造函数-这不是我的情况。

dpiehjr4

dpiehjr41#

你可以通过为你的类设置一个私有构造函数来实现这种final效果,它会阻止类被扩展,但也会阻止类被示例化(只有在同一个文件中才有可能):

class MyString {
    MyString._(); // use _ for private constructor.
  
    static void print(String s) {
      print(s);
    }
}

呼叫

String message = "Hello World";
MyString.print(message);

Dart考虑到我们都是成年人,因此防止类扩展是设计的一部分,开发人员有责任拥有清晰的类名,而不是part of the language:

避免扩展不打算成为子类的类。

如果一个构造函数从生成式构造函数变成工厂构造函数,任何调用该构造函数的子类构造函数都会被破坏。同样,如果一个类改变了它自己调用的方法,那么重写这些方法并期望它们在特定点被调用的子类也会被破坏。

final与Java的含义差异

Dart对final的定义非常简单:dart中的变量只能设置一次,id est:是“不可变的”。
Final和const如果你从来不想改变一个变量,那么就使用final或const来代替var,或者作为type的补充。

最终变量只能设置一次;const变量是编译时常量。(Const变量是隐式final的。)final顶级变量或类变量在第一次使用时初始化。

mcdcgff0

mcdcgff02#

除了将构造函数私有化并通过静态工厂示例化对象的方法之外,还可以使用包meta并将 final 类注解为sealed

@sealed
  class Z{}

这将向您的包的用户发出信号,该类不应被 * 扩展 * 或 * 实现 *。例如,在试图扩展类Z的vscode中:

class Z1 extends Z{}

将导致以下警告:

The class 'Z' shouldn't be extended, mixed in, 
or implemented because it is sealed.
Try composing instead of inheriting, or refer 
to its documentation for more information.dart(subtype_of_sealed_class)

dart分析器也会发现该问题:

$ dart analyze
Analyzing test...                      0.8s

 info • lib/src/test_base.dart:3:1 • 
 The class 'Z' shouldn't be extended, mixed in, or implemented because it
 is sealed. Try composing instead of inheriting, or refer to its 
 documentation for more information. • subtype_of_sealed_class
zf9nrax1

zf9nrax13#

可以将工厂未命名构造函数与私有命名构造函数沿着使用,如下所示:

class NonExtendable {
  NonExtendable._singleGenerativeConstructor();

  // NonExtendable();

  factory NonExtendable() {
    return NonExtendable._singleGenerativeConstructor();
  }

  @override
  String toString(){
    return '$runtimeType is like final';
  }
}

在客户端代码中、在同一个库中或在另一个库中,可以创建示例,例如:

// Create an instance of NonExtendable
  print ('${NonExtendable()}');

试图扩展它,比如

class ExtendsNonExtendableInSameLibrary extends NonExtendable {

  ExtendsNonExtendableInSameLibrary._singleGenerativeConstructor() : super._singleGenerativeConstructor();

  factory ExtendsNonExtendableInSameLibrary() {
    return ExtendsNonExtendableInSameLibrary._singleGenerativeConstructor();
  }
}

将在同一个库(同一个“源文件”)中工作,但不能在另一个库中工作,因此从任何客户端代码的Angular 来看,类NonExtendable与Java中的“final”相同。

相关问题