如何在 Dart 中创建私有变量?

我想创建一个私有变量,但我不能。

这是我的代码:

void main() {
var b = new B();
b.testB();
}


class A {
int _private = 0;


testA() {
print('int value: $_private');
_private = 5;
}
}


class B extends A {
String _private;


testB() {
_private = 'Hello';
print('String value: $_private');
testA();
print('String value: $_private');
}
}

当我运行这段代码时,会得到以下结果:

String value: Hello
int value: Hello
Breaking on exception: type 'int' is not a subtype of type 'String' of 'value'.

另外,我没有得到任何错误或警告时,编辑这个源代码。

如何在 Dart 中创建私有变量?

92372 次浏览

隐私在 Dart 中存在于图书馆,而不是类级别。

如果要将 A 类放入一个单独的库文件(例如 other.dart)中,例如:

library other;


class A {
int _private = 0;


testA() {
print('int value: $_private');  // 0
_private = 5;
print('int value: $_private'); // 5
}
}

然后导入到你的主应用程序中,比如:

import 'other.dart';


void main() {
var b = new B();
b.testB();
}




class B extends A {
String _private;


testB() {
_private = 'Hello';
print('String value: $_private'); // Hello
testA();
print('String value: $_private'); // Hello
}
}

你会得到预期的输出:

String value: Hello
int value: 0
int value: 5
String value: Hello

来自 Dart 文档:

与 Java 不同,Dart 没有 public、 protected 和 private 这些关键字。如果一个标识符以下划线 _开头,那么它对其库是私有的。

库不仅提供 API,而且是一个隐私单元: 以下划线 _开头的标识符仅在库中可见。

关于图书馆的几句话:

每个 Dart 应用程序都是一个库,即使它不使用库指令。导入和库指令可以帮助您创建模块化的、可共享的代码库。

您可能听说过 part指令,它允许您将一个库拆分为多个 Dart 文件。

Dart documentation "libraries-and-visibility"

到目前为止,最高的答案是绝对正确的。

I'll try to go into more detail in this answer.

I'll answer the question, but lead with this: That's just not how Dart is intended to be written, partly because library-private members make it easier to define operators like ==. (Private variables of a second object couldn't be seen for the comparison.)

现在我们已经把这个问题解决了,我将首先向您展示如何实现它(库-private 而不是 class-private) ,然后向您展示如何使变量 class-private,如果您仍然真的想要这样做的话。开始了。

如果一个类不想看到另一个类上的变量,你可能会问自己它们是否真的属于同一个库:

    //This should be in a separate library from main() for the reason stated in the main method below.


class MyClass {
//Library private variable
int _val = 0;


int get val => _val;
set val(int v) => _val = (v < 0) ? _val : v;


MyClass.fromVal(int val) : _val = val;
}


void main() {
MyClass mc = MyClass.fromVal(1);
mc.val = -1;
print(mc.val); //1


//main() MUST BE IN A SEPARATE LIBRARY TO
//PREVENT MODIFYING THE BACKING FIELDS LIKE:
mc._val = 6;
print(mc.val); //6
}

这应该很好。但是,如果你想要私有类数据:

Though you technically aren't allowed to create private variables, you 可以 emulate it using the following closure technique.

(HOWEVER, you should CAREFULLY consider whether you really need it and whether there is a better, more Dart-like way to do what you're trying to accomplish!)

    //A "workaround" that you should THINK TWICE before using because:
//1. The syntax is verbose.
//2. Both closure variables and any methods needing to access
//   the closure variables must be defined inside a base constructor.
//3. Those methods require typedefs to ensure correct signatures.


typedef int IntGetter();
typedef void IntSetter(int value);


class MyClass {
IntGetter getVal;
IntSetter setVal;


MyClass.base() {
//Closure variable
int _val = 0;


//Methods defined within constructor closure
getVal = ()=>_val;
setVal = (int v) => _val = (v < 0) ? _val : v;
}


factory MyClass.fromVal(int val) {
MyClass result = MyClass.base();
result.setVal(val);
return result;
}
}


void main() {
MyClass mc = MyClass.fromVal(1);
mc.setVal(-1); //Fails
print(mc.getVal());


//On the upside, you can't access _val
//mc._val = 6; //Doesn't compile.
}

所以是的,只要小心一点,试着遵循语言的最佳实践,你就会没事的。

剪辑

Apparently there's a new typedef syntax that's preferred for Dart 2. If you're using Dart 2 you should use that. Or, even better, use inline function types.

如果使用第二种方法,就不会那么冗长,但是仍然存在其他问题。

dart中,在 variable name之前使用‘ _’将其声明为 private。与其他编程语言不同,这里的 private并不意味着它只对它所在的类可用,private 意味着它是 可以在它所在的文件中访问其他文件无法访问