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

时间:2013-07-05 12:10:17

标签: 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中创建私有变量?

4 个答案:

答案 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意味着可以在其所在的文件中对其进行访问,而对其他文件则不可访问。

相关问题