我想创建一个私有变量,但我不能。
这是我的代码:
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中创建私有变量?
答案 0 :(得分:55)
来自Dart文档:
与Java不同,Dart没有关键字public,protected和private。如果标识符以下划线
_
开头,则它对其库是私有的。
库不仅提供API,而且是隐私单元:以下划线_
开头的标识符仅在库中可见。
答案 1 :(得分:19)
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
答案 2 :(得分:4)
到目前为止,最正确的答案肯定是正确的。
我将在此答案中尝试更多细节。
我将回答问题,但首先提出:这并不是Dart的编写方式,部分原因是私有库成员使定义==
之类的运算符变得更加容易。 (比较时看不到第二个对象的私有变量。)
现在我们已经解决了这个问题,我将首先向您展示它是如何完成的(库私有而不是类私有),然后向您展示如何创建变量类-私有,如果您仍然真的想要那个。我们走了。
如果一个类没有业务可以看到另一个类上的变量,则您可能会问自己,它们是否确实属于同一库:
//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
}
那应该很好。但是,如果您真的想要私人课程数据:
尽管从技术上讲,您不允许创建私有变量,但您可以使用以下闭包技术对其进行仿真。
(但是,您应该仔细考虑自己是否真的需要它,以及是否有更好的,更像Dart的方式来完成您要完成的工作!)
//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.
}
是的。只需小心并尝试遵循该语言的最佳实践,就可以了。
编辑
显然,有一种新的typedef语法是Dart 2首选的。如果您使用的是Dart 2,则应该使用它。或者,甚至更好地使用内联函数类型。
如果使用第二个,它的详细程度会降低,但是其他问题仍然存在。
答案 3 :(得分:2)
在dart中,变量名之前使用_,以将其声明为私有。与其他编程语言不同,此处的private并不意味着仅对其所在的类可用,而private意味着可以在其所在的文件中对其进行访问,而对其他文件则不可访问。