Using "final" for a Class instantiation - dart

I came across the following code the other day (below) and wondered if it achieves anything of significance in Dart other than the fact that the Class instantiation cannot be changed. I did read some SO posts regarding Java, however they didn't appear conclusive, and don't necessarily apply to Dart. I would not have coded it that way (with final), however perhaps I should. Is there any major significance to using "final" in this instance and what does it achieve?
import 'dart:math';
final _random = new Random();

From Dart: Up and Running:
If you never intend to change a variable, use final or const, either instead of var or in addition to a type. A final variable can be set only once; a const variable is a compile-time constant.
A local, top-level, or class variable that’s declared as final is initialized the first time it’s used.
So there are three benefits to using final here:
If some code erroneously tries to set _random another time, an error will be generated.
It is also clearer to other programmers (or the same programmer at a later date) that _random is never intended to be changed.
_random is not initialized until it used, so the application will start faster.
For those reasons, I would consider this a good use of final; certainly the code would "work" without it, but it's better this way.
In short, I think the book offers sound advice: "If you never intend to change a variable, use final or const".

From the documentation :
A local, top-level, or class variable that’s declared as final is initialized the first time it’s used. Lazy initialization of final variables helps apps start up faster.

Related

Why is using final, with no type, considered good practice in Dart? ie `final foo = config.foo;`?

I see this recommended in the dart style guide, and copied in tons of tutorials and flutter source.
final foo = config.foo;
I don't understand it, how is this considered best practice when the readability is so poor? I have no clue what foo is here, surely final String foo = config.foo is preferable if we really want to use final?
This seems the equivalent to using var, which many consider a bad practice because it prevents the compiler from spotting errors and is less readable.
Where am I wrong?
In a lot of cases is does not really matter what type you are using as long the specific type can be statically determined by the compiler. When you are using var/final in Dart it is not that Dart does not know the type, it will just figure it out automatically based on the context. But the type must still be defined when the program are compiled so the types will never be dynamic based on runtime behavior. If you want truly dynamic types, you can use the dynamic keyword where you tell Dart "trust me, I know what I am doing with this types".
So types should still be defined where it matter most. This is e.g. for return and argument types for methods and class variables. The common factor for this types is that they are used to define the interface for using the method or class.
But when you are writing code inside a method, you are often not that interested in the specific types of variables used inside the method. Instead the focus should be the logic itself and you can often make it even more clear by using good describing variable names. As long the Dart analyzer can figure out the type, you will get autocomplete from your IDE and you can even still see the specific type from your IDE by e.g. Ctrl+Q in IntelliJ on the variable if you ends up in a situation where you want to know the type.
This is in particular the case when we are talking about the use of generics where it can be really tiresome to write the full specific type. Especially if you are using multiple generics inside each other like e.g. Map<String, List<String>>.
In my experience, Dart is really good to figure out very specific types and will complain loudly if your code cannot be determined statically. In the coming future, Dart will introduce non-null by default, which will make the Dart compiler and analyzer even more powerful since it will make sure your variable cannot be null unless this is something you specifically want and will make sure you are going to test for null when using methods which are specified to not expecting null.
About "Where am I wrong?". Well, a lot of languages have similar feature of var/final like Dart with the same design principle about the type should still be statically determined by a compiler or runtime. And even Java has introducing this feature. As a experienced Java and Dart programmer I have come to the conclusion for myself that typing inside methods are really not that important in a lot of cases as long I can still easily figure out the specific type by using an IDE when it really matters.
But it does make it more important to name your variables so they are clearly defining the purpose. But I am hoping you already are doing that. :)

Can late and final be used together?

I am trying NNBD as of now and I would like to know if you can use the new keyword late and final together.
From what I understood, a late property can be set anywhere. You are basically telling the analyzer that it will not be null when used.
I think that is kinda dangerous in some situations.
So I am wondering if you can add a late final in NNBD, this would tell the analyzer that the property must be initialized within the class constructor.
There is a question similar but I guess there wasn't null safety at the time:
Dart. Late initialize final variables
You can declare a late final variable.
If you declare it with an initializer, late final foo = computeSomething();, then it is a lazy final variable. You can't assign to the variable, but its value is only computed the first time the variable is read. (In my experience, this is never the right choice for local variables, even though the language allows it. If you care about lazy initialization of a local variable, you also almost always want to know whether it was initialized, and a lazy variable doesn't give you that information. It's also confusing that the code is executed out-of-order, and it doesn't allow you to use await in the initializer expression).
If you declare a late final variable without an initializer, you are allowed to write to the variable once. Because the variable is late, the compiler won't complain about assignments at compile-time, unless it's absolutely certain that you have assigned the variable already, and only if it's a local variable (because that's the only variables that the compiler attempts to track assignments to).
If the late final variable without an initializer is an instance member of a class, that means that the class interface has a setter. You need to be very, very careful about exposing late final variables in the public API of a class. (Read: Don't do that!)
It's better to use late variables internally and guard access to the fields, so you can ensure that nobody assigns the variable twice. The goal of a late final variable is not to throw if it's assigned twice. It should never be assigned twice. It's there to allow allow code which knows for some reason that the compiler cannot comprehend, that the variable is only assigning once. So, only allow access to late final variables to code which are aware of that reason, and which maintains the invariant.
Yes!
You can see this pattern commonly used when initializing AnimationController.
class _MyState extends State<MyPage> with SingleTickerProviderStateMixin {
late final AnimationController _controller;
#override
void initState() {
super.initState();
_controller = AnimationController(vsync: this);
}
}
And you can use it for lazy initialization, like:
class Foo {
late final int i = calculate; // Initialized only when used.
int get calculate => ...;
}
Short answer: No, you'll not get any help from the analyzer.
From the nnbd language spec:
It is an error if a top level variable or static variable with a
non-nullable type has no initializer expression unless the variable is
marked with a late or external modifier.
It is an error if a class declaration declares an instance variable
with a potentially non-nullable type and no initializer expression,
and the class has a generative constructor where the variable is not
initialized via an initializing formal or an initializer list entry,
unless the variable is marked with a late, abstract, or external
modifier.
late final int foo; basically turns off null awareness for foo. It seems to be the equivalent of using implicitly unwrapped optionals in Swift, which can be hazardous, if you familiar with that.
https://github.com/dart-lang/language/blob/master/accepted/future-releases/nnbd/feature-specification.md
Besides that, the static analyzer does not warn you about trying to reset a late final.
Let D be a late and final local variable declaration named v. It is a run-time error, throwing an instance of LateInitializationError, to assign a value to v if a value has previously been assigned to v.
https://github.com/dart-lang/language/blob/master/accepted/future-releases/nnbd/feature-specification.md#late-fields-and-variables
Using late means you need to know exactly when things are being initialized and used.

DartPad, order of execution, Just In Time?

I'm new to Dart (from JS) and I'm trying to make sense of this simple program.
When declaring variables and setting then outside in the top part of a program, it seems like (???) the assignment doesn't happen before main() is executed. See below.
List<int> a1=[1,2,3];
List<int> b1=new List.from(a1);
void main() {
a1.add(9);
print(a1); // [1,2,3,9]
print('b1 $b1'); // CONFUSING [1,2,3,9] (I expected [1,2,3])
List<int> a2=[1,2,3];
List<int> b2=new List.from(a2);
a2.add(77);
print(a2); // [1,2,3,77]
print('b2 $b2'); // [1,2,3], as expected
}
Is this because there is some Just In Time (JIT) code execution? Or that assignments happen later, like with some JS gotchas. I did try to read the docs on this but could not figure out anything with code execution order.
I'm most interested in learning how I would learn this myself. So any links to the proper section of the docs is appreciated.
PS. In JS, Chrome Developer Tools gives a handy debugger with breakpoints and I usually use this to check execution order bugs.
Thanks in advance.
It's not JIT, just lazy initialization of global variables.
Dart ensures that no user code runs before the start of main. To ensure that, it lazily initializes global and static variables the first time they are read. That does mean that you should be careful when your global variable initializer refers to mutable objects.

What's with the final/const craze in Flutter?

Java have final as well as Dart, but as far as I have seen, most Java people avoid using it all the time, since it can make your code less readable. For example, final is used all the time in class constants such as public static final int, but most people avoid using it in a method variable, since it's just seen as "excessive code correctness" by many developers, adding to boilerplate code.
C++ also has const and it can get crazy with it:
char ** const * const x // declare x as const pointer to const pointer to pointer to char
Now I am starting to learn Flutter and I am seeing final and const all over the place. Are those really necessary, like when they say:
Fields in a Widget subclass are always marked "final".
Or can they be treated as "excess of code correctness" and be removed?
Sorry if maybe my question is too stupid, I am really new to Dart and Flutter and I don't know all the side effects/benefits of using final and const, to justify the additional attention of when to remember to use them in my code.
const means that the value of the variable is known at compile time and it is going to be constant for the whole duration of the application.
Since the value is known at compile time, you can make the necessary optimisations.
final means that the value will be constant or immutable from the moment it is set. But it is set at runtime. So you don't know it at compile time and you can't optimise it.
If you don't use final you lose the immutability feature to what you should adhere in Flutter. You should always create a widget, not modify it. And the way to enforce that is to make all its fields final.
All these finals are not here just for fun. Flutter revolves around immutability. final is a neat way to enforce that immutability, ensuring you are correctly following the different design patterns.
They are definitely not "excess of correctness" no. They exists to assure a maintainable app. 2 characters is absolutely worth the effort
The main upside of using const is that, in a reactive UI like Flutter where large parts of the widget tree may be rebuilt regularly, every single object (and all of its own variables) of every single widget will need to be recreated on every rebuild, except if they are marked const, in which case the same instance will be reused throughout the lifetime of the app.
Even with a moderately complex UI this will quickly save thousands of object instantiations, which can be significant especially when animating widgets. So, it is considered a good practice to use const when possible.
final is different, it doesn't bring any performance benefits and is mainly a way to ensure that you are following Flutter design patterns. In my opinion it improves readability in the way that knowing quickly what is immutable and what is not can be very important when developing with Flutter.

Regarding F# Object Oriented Programming

There's this dichotomy in the way we can create classes in f# which really bothers me. I can create classes using either an implicit format or an explicit one. But some of the features that I want are only available for use with the implicit format and some are only available for use with the explicit format.
For example:
I can't use let inline* (or let alone) inside an explicitly defined class.
The only way (that I know) to define immutable public fields (not properties*) inside an implicitly defined class is the val bla : bla syntax.
But there's a redundancy here. Since I'll end up with two copy of the same immutable data, one private, one public (because in the implicit mode the constructor parameters persist throughout the class existence)
(Not so relevant) The need to use attributes for method overloading and for field's defaults is rather off putting.
Is there anyway I can work around this?
*For performance reasons
EDIT: Turns out I'm wrong about both points (Thanks Ganesh Sittampalam & MichaelGG).
While I can't use let inline in both implicit & explicit class definition, I can use member inline just fine, which I assume does the same thing.
Apparently with the latest F# there's no longer any redundancy since any parameters not used in the class body are local to the constructor.
Will be gone in the next F# release.
This might not help, but you can make members inline. "member inline private" works fine.
For let inline, you can work around by moving it outside the class and explicitly passing any values you need from inside the scope of the class when calling it. Since it'll be inlined, there'll be no performance penalty for doing this.

Resources