Dart
Here is a short intro to Dart.
Variables
Variables are constructed using var
:
var myVariable = 4
Dart is statically typed: If you assign a value with a new type to your variable, you need to cast it to that type first. If you create a variable, but don’t initialize it directly, it has the datatype “dynamic”:
var a;
= 123; // this is fine
a = "foo"; // this is fine as well a
You can create uninitialized static typed variables, by displaying their type:
String a;
int b;
dynamic c; // c is of course dynamic and not static
Null safety
Since common variables can be of a certain type and null, you can run into trouble at runtime e.g. if a color for your app-background is not a hex-code but null. This will crash your app.
If you want to allow null-values, you deinfe a variable with a ?
: Color? myColor;
If you did not explicitly tell dart that your variable can be null, dart will warn you if you use it e.g. as an argument. It will also tell you to add null checks(if (myColor == null) doSomething();
) or catch errors. A nullable variable cannot be given as an argument to a function that takes non-nullable types.
Forcing a nullable value (similar to writing a null-check and throwing an exception if it fails). Only to be done if you are 100% sure the variable is not null eventhough the type is nullable:
void setBackground(Color color){
/// ...
}
? myColor = getColor();
Colorif (colorInCataloge == true) { // you have other way of checking that the type is not null
!);
setBackground(myColor}
If you declare a non-nullable variable but initialize it later, the type-checke would assume that it could be none. Using the keyword late
, you can tell the type-checker that you will initalize it with a non-null value later: late myVariable myType;
Constants / Final
You can set your “variables” in stone during compilation using const
keywords:
const int myConstant = 2; // this can never change again
If you have a “variable” be set in stone only during run-time, you use final
:
final int time = currentTime; // you cannot set the current time during compilation
Lists
If you define collections, you can set the type of elements that they contain (e.g. widgets):
List <Widget> myWidgetList = [];
Conditionals
… look like this:
if (1==1 && myAnswer == true || !(5<2)) {
do_something;} else if (myChocolate == "black"){
do_something_else;} else {
do_whatever;}
Ternary Operators
To make your code more concise you can assign one of two possible values to a variable depending on a condition:
int myAge = 17;
= myAge >= 18 ? "here is your booz" : "you are too young"; str answer
i.e. if the condition in front of the ?
is true, you use the first value (before :
) otherwise the second value.
Functions
Named function
void myFunction(){...}
void
: The type of the output of the function
myFunction
: The function name
()
: The input of the function
{...}
: The body of the function (the commands)
If you want to be able to call the parameters of your function by name, you need to define them in curly brackets: void myFunction({int n1, int n2}{}
Anonymous function
This is often used, if you define a function on the fly as an argument for another function. Btw: You can pass functions just like any other variable.
{...} // lacks a name ()
Arrow function
This is a short form of the curly-braces syntax. It returns everything behind the fat arrow:
int multiply(int n, int m)=>n*m;
is the same as
int multiply(int n, int m){
return n * m;
}
You can also use this with a void return type.
Asynchronous code
Asynchronous code contains parts, where the process has to wait (e.g. for a response from REST-API) to continue.
void myfunction() async {
var response = await http.get("htttp//example.com/params")
}
while it awaits, other parts of the program can run. You need to mark functions with asynchronous code as async
.
Isolates
If you have computation-heavy code, it can make your app lag. To avoid this, you can use multi-processing: You run the computatin-heavy parts and the rest on different threads.
### Futures
If you have to wait for async code, you can also use Futures in your function:
Future<String> getVerificationURL() {
return Future.value(
'https://example.com');
}
The type of the return value will be at first uncompleted (Future
) and later completed with data or completed with error. You handle these three phases like this:
final myFutureResult = getVerificationURL();
.then((response){ // this will be executed, once the process behind the future variable is complete
myFutureResult
print(response)}).catchError((error) {// you need this in case the response is an error.
'You have an $error');
print(}
);
or
try{
final myFutureResult = await getVerificationURL();
}
catch(error){
'You have an $error')
print(}
### Streams
A stream can generate more than one method. You use a listener to catch the results of the stream.
// Create stream
final myStream = NumberCreator().stream;
// Subscribe to stream
final subscription = myStream.listen(
=> print('single stream response: $result'),
(result) : (error) => print('You have an $error'),
onError: () => print('stream is done'),
onDone
);
// control flow of data
.pause()
subscription.resume()
subscription.cancel() subscription
Every time a new value is emitted by the stream, the listen-function is called. Normal streams are set up for single subscription. If you want to use multiple subscriptions, you use StreamingObject().stream.asBroadcastStream;
.
Classes
class MyClass {
// define some class variables / properties:
String myString;
// define a constructor:
{String myText}) { // name must be the same as class name
MyClass(this.myString = myText; // this references object properties
}
void do_something() {
...
}
}
You can use syntactic sugar to make your constructor more concise:
...
String myString;
this.myString);
MyClas(...
Inheritance
to inherit properties and functions from other classes, we use extends
:
class JetPlane extends Plane{
...
}
Polymorphism
If you want to use some methods/properties of a class but override others, you use @override
:
class UFO extends Plane{
@override
void fly(){
"hover around");
print(}
}
you can also add onto the methods of the other class using super
:
class UFO extends Plane{
@override
void accelerate(){
super.accelerate();
= speed+500;
speed}
}
Enums
Enums are like booleans with more options. Your variable can be in one of multiple states:
enum myEnum = {forward, parked, reverse};
.forward myEnum
Beware: You cannot create enums within classes.
Comments