2017-02-06

Dart for Java developers: a visibilty primer

In the previous installments of my small series about Dart for Java developers we saw quite a few lines of code. ...that is, if you looked at the .dart files I linked to. ;-) You may have wondered why some identifiers start with an underscore. I briefly mentioned libraries and packages, but did not say much about visibility or scope. The underlying questions are
  • Where can I see a variable, function or method?
  • Where and when can I access them?
Consider the following source file named a.dart:

var answer = 42;
main() {
  var a = answer;
  {
    var b = a;
    print(b);
  }
  print(b);
}

It will print 42 once, but then fail with a NoSuchMethodError. That happens because there is no top-level getter b. To a Java developer it will not be surprising that print(b); outside the nested block fails, as b is not visible here. But why do we see NoSuchMethodError? Didn't I just access an identifier?

In Dart access to variables occurs via getters and setters, and if these have not been defined by the developer, they will be there automatically. If we remove the second print(), the program will run just fine (assume a version named a_correct.dart). Now take a look at the following lines of code:

import "a_correct.dart";
main() {
  print(answer);
}

If we run it, 42 is printed once. In a_correct.dart answer has been declared at the top-level, so the identifier can be seen by the library that imports a_correct.dart. But what if we don't want a variable or function be visible? Just prefix the identifier with an underscore. Imagine a file b.dart:

var _answer = 42;
_hello() {
  print(_answer);
}

And c.dart:

import "b.dart";
main() {
  print(_answer);
  _hello();
}

Not to much surprise, it will fail. Neither _hello() nor _answer are visible. There is more control about what packages export to the outside world, but this is an advanced topic I might cover later. So, for now dear Java devs, just forget about publicprivate and protected. And stick to this simple rule:

If it's local, prefix the identifier with an underscore.

Clear. Precise.

No comments:

Post a Comment