Reputation: 1
I'm learning dart, I have questions. Used google translator. I apologize for possible inaccuracies.
class A {
// no errors when compile code
static int x = y;
static int y = x;
}
void main() {
/* compile error
int a = b;
int b = a;
*/
print(y);
print(x);
}
// no errors when compile code
int x = y;
int y = x;
If non-top-level identifiers are used, then the same principle as in c/c++ is used. If identifier a uses identifier b, then identifier b must be higher in the code.
But for top-level identifiers, the situation is somehow different. Probably, this was done for convenience in the case of a cyclic relationship between functions, classes, that is, strange situations. An example of a situation is this. If two variables refer to each other, then an error occurs and a recursive initialization attempt occurs. That is, the variables behave like functions that call each other.
If you assign a value to the x variable inside main, then there will be no error due to recursion, in this case, apparently, the original initializer is ignored.
main() {
x = 1;
print(x);
print(y);
}
int x = y;
int y = x;
If it does not make it difficult to answer the question, indicate its number.
Upvotes: 0
Views: 92
Reputation: 71773
In short:
Because local variables are declared during statement execution, which has ordering, and non-local variables are not.
Yes. Non-local variables are getters/setters.
Correct.
Yes. Local ariables can only be used after their declaration has been executed.
Yes.
In general, you cannot read a variable before it has been initialized. What that means depends on the variable.
A local variable is initialized when statement execution reaches the declaration. That means that you cannot refer to local variables until after the declaration. A non-nullable local variable with no initializer expression (like int x;
) is not initialized when it's executed. You must assign to it before you can read it. It's usually possible for static analysis to figure out whether a variable has been initialized, and that makes it a compile-time error to access the variable before it's definitely assigned.
(Parameters are local variables which are always initialized when the function is entered, so they are simpler.)
Outside of statement code, there is no order to execution, which is why local and non-local variables behave differently.
Global (top-level/static, which are treated the same) variables with initializer expressions (Foo x = somethingFoo();
) are initialized lazily when they are first read or written to. The ordering of these declarations do not matter. If the variable has no initializer, it must be nullable, and is treated as having = null
as initializer (unless late
).
Instance variables are initialized when the object is created, by the constructor initializer list, which means they are always initialized when you have a reference to the object.
A local or instance variable marked late
is lazily initialized when read or written, just as top-level variables. If it has no initializer expression, it's a run-time error to read before the variable has been written.
All non-local variables are treated as a pair of a getter and setter (unless final
and non-late
, then it's just the getter).
Here is a quick summary of the ways to declare variables:
Variable Type | Initialized | Can assign | ||||||
---|---|---|---|---|---|---|---|---|
Parameter | int |
x |
on function entry | Any time | ||||
final |
int |
x |
on function entry | Never | ||||
Local | int |
x |
; |
When definitely assigned to. | Any time | |||
int? |
x |
; |
When executed, to null . |
Any time | ||||
int |
x |
=4; |
When executed, to 4 |
Any time | ||||
final |
int |
x |
; |
When definitely assigned. | When definitely unassigned. | |||
final |
int |
x |
=4; |
When executed, to 4 |
Never | |||
late |
int |
x |
; |
When assigned. | Any time | |||
late |
int |
x |
=4; |
When read (to 4) or assigned. | Any time | |||
late |
final |
int |
x |
; |
When assigned. | Any time, throws if already assigned. | ||
late |
final |
int |
x |
=4; |
When read, to 4 |
Never | ||
Static or top-level | static |
int |
x |
; |
INVALID | |||
static |
int? |
x |
; |
When read, to null , or assigned. |
Any time. | |||
static |
int |
x |
=4; |
When read or assigned. | Any time | |||
static |
final |
int |
x |
; |
INVALID | |||
static |
final |
int |
x |
=4; |
When read or assigned. | Never | ||
static |
late |
int |
x |
; |
When assigned. | Any time, throws if not assigned. | ||
static |
late |
int |
x |
=4; |
When read (to 4) or assigned. | Any time, throws if not assigned. | ||
static |
late |
final |
int |
x |
; |
When assigned. | Any time, throws if already assigned. | |
static |
late |
final |
int |
x |
=4; |
When read, to 4 |
Never | |
Instance | int |
x |
; |
By constructor. | Any time | |||
int? |
x |
; |
By constructor, to null if not otherwise. |
Any time | ||||
int |
x |
=4; |
By construction. | Any time | ||||
final |
int |
x |
; |
By constructor. | Never | |||
final |
int? |
x |
; |
By constructor, to null if not otherwise. |
Never | |||
final |
int |
x |
=4; |
By construction. | Never | |||
late |
int |
x |
; |
By constructor or when assigned | Any time, throws if not assigned | |||
late |
int |
x |
=4; |
By constructor, when read or when assigned | Any time, throws if not assigned. | |||
late |
final |
int |
x |
; |
By constructor or when assigned. | Any time, throws if already assigned | ||
late |
final |
int |
x |
=4; |
When read. | Never |
Example code showing this: https://dartpad.dev/?id=c239a391f58e69684f77dda9d4922dac
Upvotes: 1