Description
A declaration of a name that starts with _
is private to the current library, unless the declaration is
- a local variable (where privacy makes no difference),
- a label (where privacy also makes no difference, and which is in its own namespace anyway), or
- a formal parameter (where the meaning of privacy has never been fully resolved)
Concretely, the tools are currently dealing with named formal parameters whose name starts with _
in slightly different ways:
// ----- Library 'n011lib.dart'.
class A {
A({_name});
void m({_name}) {}
}
class B {
B({required _name});
void m({required _name}) {}
}
// ----- Library 'n011.dart'.
import 'n011lib.dart';
void main() {
var a = A(_name: 0);
a.m(_name: 0);
var b = B(_name: 0);
b.m(_name: 0);
}
With the analyzer (commit 92638bf5d3a5668920d0a40a4b24a6a97f982b3f), no issues are reported; that is, _name
is treated like any other name when it occurs as the name of a named parameter, required or not (that is, it isn't treated as a private name).
But the common front end reports an error for both cases with the declaration of A
(effectively saying "a named parameter name cannot be private", so we cannot even ask how it's treated at call sites), and allows class B
(.. "except if it's required").
We could say that a formal parameter name starting with _
is simply a name like all others, with no special exceptions. In particular, call sites in different libraries can invoke the enclosing function/method/constructor and pass an actual argument to a named parameter with such a name.
We could also say that a formal parameter name starting with _
is a private name. So if it's the name of a named parameter then it can't be passed at call sites in other libraries.
The former makes it easy to use named initializing formals to initialize private instance variables (and the name _name
in the parameter declaration this._name
serves as documentation for the fact that we're initializing a private instance variable), but it is unfortunate that this usage will make it harder to rename said instance variable. (It would be nicer if the API would only reveal that we're initializing a private instance variable, and it wouldn't mention the name.)
The latter provides support for a very special kind of privacy: Every caller outside the library must use the default value for a non-required named formal parameter with that kind of name, and the whole function/method/constructor can't be called at all outside the library if the parameter is required. This feature is again potentially useful, but rather accidental in nature.
At the conceptual level it may seem inconsistent to claim that _name
is just another name (not private to any library) when it's used as the name of a named initializing formal this._name
, because it does refer to the instance variable whose name is definitely private.
So we need to clarify these issues and then ensure that implementations agree. We have the freedom to make different choices, because current code is (in practice) unable to depend on any particular behavior in the case where the tools behave differently.
Metadata
Metadata
Assignees
Type
Projects
Status