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



在Java\Kotlin中,我们有一个String类,它是最终的且不可变的。

我试图用final关键字标记类,但看起来这是不允许的。

所以,我有点困惑,如何在Dart中声明最终类?

注意:情况是-我想在外部实例化这个类,但禁止扩展它。所以使用私有构造函数-这不是我的情况

您可以通过为类提供私有构造函数来从java实现这种final效果,这将防止类被扩展,但也会防止类被实例化(仅在同一文件中两者都有可能(:

class MyString {
MyString._(); // use _ for private constructor.

static void print(String s) {
print(s);
}
}

使用呼叫

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

Dart认为我们都是成年人,因此防止类扩展是设计的一部分,开发者有责任拥有清晰的类名,而不是语言的一部分:

避免扩展一个不打算被子类化的类
如果构造函数从生成构造函数更改为工厂构造函数,则调用该构造函数的任何子类构造函数都将中断。此外,如果一个类更改了它在此调用的自己的方法中的哪一个,这可能会破坏覆盖这些方法的子类,并期望它们在某些点被调用。


final与Java的含义差异

Dart对什么是final有一个非常简单的定义:Dart中的变量只能设置一次,id est:是不可变的。

词尾和常量如果您从未打算更改变量,请使用final或const来代替var或添加到类型中
最终变量只能设置一次;const变量是一个编译时常量。(Const变量是隐式的final。(final顶级或类变量在第一次使用时初始化。

除了使构造函数私有化并通过静态工厂实例化对象的方法外,您还可以使用包meta和将最终类注释为密封:

@sealed
class Z{}

这将向包的用户发出信号,表示此类不应被扩展或实现。例如,在vscode中,尝试扩展类Z:

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 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

您可以使用工厂命名构造函数和私有命名构造函数,如下所示:

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();
}
}

将在同一个库(相同的"源文件"(中工作,但不能在另一个库中工作,从任何客户端代码的角度来看,使类NonExtendable与Java中的"final"相同。

最新更新