DEV Community

Cover image for Flutter Series - Dart for Flutter
Tanweer Anwar
Tanweer Anwar

Posted on • Updated on

Flutter Series - Dart for Flutter

Do you want to build cool mobile apps that you can show to the world? Do you find native mobile development difficult? Do you want to build feature-rich app quickly?
If your answer to any of the above question is "yes", then don't worry Flutter is here for you. In this series, I will try to cover all the concepts of that you are required to know to build an app. Starting from the very basic ie. Dart language itself.

Flutter

According to Google, creator of the framework:
Flutter SDK is Google's UI toolkit for crafting beautiful, natively compiled applications for mobile, web, and desktop from a single codebase.
In simple words, it is a framework to build applications with beautiful UI that provides native performance. You can build apps for different platform such as mobile, web or desktop(support for even more platform is coming soon) using Flutter and that too with a single codebase🚀.

In this series, there will be a number of posts. Each covering certain concepts which you should to know to take full advantage of Flutter. This series will be structured in a way so that you incremently learn new concepts and use it in your app. Today's post will be about the basics of Dart, language in which flutter apps are written.

Let's get started

Dart

Dart is an object oriented, high level language like python, java or c++. It is used to build mobile, web and desktop applications.

Before starting I want to point out that you can run all the below example in DartPad Open DartPad.
Just make sure to write all your code in main() function.

So let's start with all the dart concepts you should know to start with flutter.

Variables

You can define variables in Dart using var keyword:

var name = 'Bob';
Enter fullscreen mode Exit fullscreen mode

Dart compiler implicitly infer variable name to be of String datatype.

You can explicitly declare the datatype of a variable like this:

String name = 'Bob';
Enter fullscreen mode Exit fullscreen mode

Dart is statically-typed language, meaning type checking is done at compile time. Whenever you try to assign variable of a particular datatype with data of different type, it will result in assignment error.

For example:

var name = 'Bob';
name = 1;
Enter fullscreen mode Exit fullscreen mode

which result in:

Error: A value of type 'int' can't be assigned to a variable of type 'String'.
Enter fullscreen mode Exit fullscreen mode

If a variable isn’t restricted to a single type, specify the Object or dynamic type:

dynamic name = 'Bob';
Enter fullscreen mode Exit fullscreen mode

You can assign name variable to any other type at a later stage without any error like:

name = 123;
Enter fullscreen mode Exit fullscreen mode

Uninitialized variables have an initial value of null.

int count;
print(count);
Enter fullscreen mode Exit fullscreen mode

Output:

null
Enter fullscreen mode Exit fullscreen mode

Final and const
If you want to make a variable read-only, declare it as final using final keyword. A final variable can be set only once.
Changing it again results in Error: a final variable can only be set once.
Example:

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
Enter fullscreen mode Exit fullscreen mode

If you try to change name variable it will result in error.

name = 'Alice';
Enter fullscreen mode Exit fullscreen mode

Output:

Error: Can't assign to the final variable 'name'.
Enter fullscreen mode Exit fullscreen mode

const is used for variables that you want to be compile-time constants. const variables can only assigned with a expression which always returns a constant value.
Example:

const a = 2 * 3;
Enter fullscreen mode Exit fullscreen mode

This is valid because 2 * 3 will always return a constant value ie. 6.
But if you try to do something like this:

int a = 3;
const b = 2 * a;
Enter fullscreen mode Exit fullscreen mode

Results in:

Error: Not a constant expression.
Enter fullscreen mode Exit fullscreen mode

because value of variable a can change. So, this expression is not constant.
You can’t change the value of a const variable just like final variable:

const a = 1;
a = 2; // Error: Constant variables can't be assigned a value.
Enter fullscreen mode Exit fullscreen mode

If you want to define a class variable(variable defined at class level) as const, define it as static const.

Built-in types in dart
The Dart language has special support for the following types:

  • numbers
  • strings
  • booleans
  • lists (also known as arrays)
  • sets
  • maps
  • runes (for expressing Unicode characters in a string)
  • symbols

Numbers
Dart numbers come in two types ie. int and double.
int represents integer value while double represents floating or decimal point values.
Example:

int count = 5;
double temperature = 25.5;
Enter fullscreen mode Exit fullscreen mode

String
A Dart string is a sequence of characters. You can use either single or double quotes to create a string:

String s1 = 'Single quotes work well for string literals.';
String s2 = "Double quotes work just as well.";
String s3 = 'It\'s easy to escape the string delimiter.';
String s4 = "It's even easier to use the other delimiter.";
Enter fullscreen mode Exit fullscreen mode

You can put the value of an expression inside a string by using ${expression}. If the expression is an identifier, you can skip the {}.
Example:

double temperature = 16.0;
String s1 = 'Current temperature: ${(temperature * 9/5)+ 32}Fahrenheit';
int count = 10;
String s2 = 'Total count: $count';
Enter fullscreen mode Exit fullscreen mode

You can concatenate strings using adjacent string literals or the + operator:

String s1 = 'String ' 'concatenation';
String s2 = 'String ' + 'concatenation';
print(s1);
print(s2);
Enter fullscreen mode Exit fullscreen mode

Output:

String concatenation
String concatenation
Enter fullscreen mode Exit fullscreen mode

String type have a number of in-built methods(functions) which you can use to modify the string.

toUpperCase(): Converts all characters in the string to upper case.

toLowerCase(): Converts all characters in the string to lower case.

substring(int startIndex, [int? endIndex]): Returns the substring of this string that extends from startIndex, inclusive, to endIndex, exclusive.

contains(Pattern other, [int startIndex = 0]): Returns true if the string contains a match of other string.

compareTo(String other): Compares this string to other. It returns an integer based on comparison.

indexOf(Pattern pattern, [int start = 0]): Returns the position of the first match of pattern in this string, starting at start, inclusive.

startsWith(Pattern pattern, [int index = 0]): Returns true if this string starts with a match of pattern.

endsWith(String other): Returns true if this string ends with other.

Example:

String s = 'Hello from dart world';
print(s.toUpperCase());
print(s.toLowerCase());
print(s.substring(0,5));
print(s.contains('dart'));
print(s.compareTo('Hello World'));
print(s.indexOf('dart'));
print(s.startsWith('Hello'));
print(s.endsWith('dart'));
Enter fullscreen mode Exit fullscreen mode

Output:

HELLO FROM DART WORLD
hello from dart world
Hello
true
1
11
true
false
Enter fullscreen mode Exit fullscreen mode

Parameters in [] are optional.

There are many more in-built string methods in dart which I have not covered. You can find all the other methods here.

Conditional property access(?)
if s is null or uninitialized, it will cause exception Cannot read property of null. To avoid that dart has introduced a conditional property access operator(?). You can use it like String s2 = s?.toUpperCase();.
So if s is null, then instead of resulting in exception s2 will become null too.

Null-aware operator(??)
Null-aware operator(??) returns the expression on its left unless that expression’s value is null, in which case it evaluates and returns the expression on its right. In the above example if you want to assign a default value, use it with null-aware opeator(??):

String s;
String s2 = s?.toUpperCase() ?? "Empty String";
Enter fullscreen mode Exit fullscreen mode

Output:

Empty String
Enter fullscreen mode Exit fullscreen mode

Booleans
To represent boolean values, Dart has a type named bool. Only two values can be assigned to it true and false.
Example:

bool a = true;
String s = '';
bool isEmpty = s.isEmpty;
Enter fullscreen mode Exit fullscreen mode

Unlike other languages, you cannot use non boolean values as a condition. if(nonBooleanValue) is invalid.

Lists
In Dart, List is a collection of similar objects like arrays in other languages, so most people just call them lists.
Here is a simple list:

var list = [1, 2, 3];
Enter fullscreen mode Exit fullscreen mode

Dart compiler infer type of list variable as List<int>.If you try to add non-integer objects to this list, the analyzer or runtime raises an error.
Error: A value of type 'String' can't be assigned to a variable of type 'int'.

You can define type of list explicitly as List<type>. For example list of int can be assigned a type List<int>.

List index starts at 0 and goes upto length of the list - 1.
You can use .length to find length of string.
Example:

List<int> list = [1, 2, 3, 4, 5];
print(list.length);
Enter fullscreen mode Exit fullscreen mode

Output:

5
Enter fullscreen mode Exit fullscreen mode

You can combine two lists using + operator:

List<int> list = [1, 2];
List<int> list1 = [3,4];
List<int> list2 = list + list1;
print(list2);
Enter fullscreen mode Exit fullscreen mode

Output:

[1, 2, 3, 4]
Enter fullscreen mode Exit fullscreen mode

Dart 2.3 introduced the spread operator (...).
For example, you can use the spread operator (...) to insert all the values of a list into another list:

var list = [1, 2, 3];
var list2 = [0, ...list];
print(list2);
Enter fullscreen mode Exit fullscreen mode

Output:

[0, 1, 2, 3]
Enter fullscreen mode Exit fullscreen mode

If list is null. It will cause exception. To avoid that you need to first check for null and then do the operation. This also can be achieved using a null-aware spread operator (...?):

var list;
var list2 = [0, ...?list];
print(list2);
Enter fullscreen mode Exit fullscreen mode

Output:

[0]
Enter fullscreen mode Exit fullscreen mode

Dart 2.3 also introduced collection if and collection for, which you can use to build collections using conditionals (if) and repetition (for).

bool promoActive = true;
var nav = [
  'Home',
  'Furniture',
  'Plants',
  if (promoActive) 'Outlet'
];
var listOfInts = [1, 2, 3];
var listOfStrings = [
  '#0',
  for (var i in listOfInts) '#$i'
];
print(nav);
print(listOfStrings);
Enter fullscreen mode Exit fullscreen mode

Output

[Home, Furniture, Plants, Outlet]
[#0, #1, #2, #3]
Enter fullscreen mode Exit fullscreen mode

You can use .add() method to add values at the end of list:

var list = [1, 2, 3];
var list2 = list.add(4);
print(list2);
Enter fullscreen mode Exit fullscreen mode

Output:

[1, 2, 3, 4]
Enter fullscreen mode Exit fullscreen mode

Map
A map is an object that associates keys and values. Both keys and values can be any type of object. Each key occurs only once, but you can use the same value multiple times. Dart support for maps is provided by map literals and the Map type.
Example:

var elements = {
  // Key:    Value
  'first': 'hydrogen',
  'second': 'helium',
  'third': 'lithium'
};

var nobleGases = {
  2: 'helium',
  10: 'neon',
  18: 'argon',
};
Enter fullscreen mode Exit fullscreen mode

Dart infer type of elements as Map<String, String> and nobleGases as Map<int,String>.If you try to add the wrong type of value to either map, the analyzer or runtime raises an error.
You can create the same objects using a Map constructor:

var elements = Map();
elements['first'] = 'hydrogen';
elements['second'] = 'helium';
elements['third'] = 'lithium';

var nobleGases = Map();
nobleGases[2] = 'helium';
nobleGases[10] = 'neon';
nobleGases[18] = 'argon';
Enter fullscreen mode Exit fullscreen mode

You can add new key-pair value to existing map as:
elements['fourth'] = 'beryllium';
You can retrieve a value from map using its key.
String thirdElement = elements['third'];
If you look for a key that isn’t in a map, you get a null in return:
print(elements['fifth']);
Output:
null
Use .length to get the number of key-value pairs in the map:

Map<int, String> numberToString = {
  1: 'one',
  2: 'two',
  3: 'three',
  4: 'four',
  5: 'five'
};
print(numberToString.length);
Enter fullscreen mode Exit fullscreen mode

Output:

5
Enter fullscreen mode Exit fullscreen mode

As of Dart 2.3, maps support spread operators (... and ...?) and collection if and for, just like lists do:

Map<String,int> map = {
  "violet": 1,
  "indigo": 2,
  "blue": 3
};
Map<String, int> map2 = {
  "green": 4,
  "yellow": 5,
  "orange": 6,
  "red": 7
};
Map<String, int> coloursOfRainbow = {...map, ...map2};
print(coloursOfRainbow);
Enter fullscreen mode Exit fullscreen mode

Output:

{violet: 1, indigo: 2, blue: 3, green: 4, yellow: 5, orange: 6, red: 7}
Enter fullscreen mode Exit fullscreen mode

Conditional statement
Dart support if and else statement, like any other high level language.
if statement contains a boolean expression. Followed by a block of statement which execute only when boolean condition is true. if block can be followed by an else block which only executes when boolean condition for if block is not satisfied.

if(boolean_expression){ 
   // statement(s) will execute if the Boolean expression is true. 
} else { 
   // statement(s) will execute if the Boolean expression is false. 
}
Enter fullscreen mode Exit fullscreen mode

Conditional expressions
Dart lets you concisely evaluate expressions that might otherwise require if-else statements:
condition ? expr1 : expr2
If condition is true, evaluates expr1 (and returns its value); otherwise, evaluates and returns the value of expr2.
Example:

int age = 21;
String result = age >= 18 ? 'Eligible to vote' : 'Not Eligible to vote';
print(result);
Enter fullscreen mode Exit fullscreen mode

Output:

Eligible to vote
Enter fullscreen mode Exit fullscreen mode

Loops
Loops are used execute a series of statements repeatedly for a number of times.Dart support generally 4 types of looping statement.

1. for loop
The for loop is used when we want to execute block of code known times. In Dart, basic for loop is similar as it is in C. The loop takes a variable as iterator and assign it with an initial value, and iterate through the loop body as long as the test condition is true.
Syntax:

for(initialization;conditions;increment/decrement) {
  //body of loop
}
Enter fullscreen mode Exit fullscreen mode

Example:

int count = 5;
for(int i = 1; i <= count; i++) {
  print('#$i');
}
Enter fullscreen mode Exit fullscreen mode

Output:

#1
#2
#3
#4
#5
Enter fullscreen mode Exit fullscreen mode

2. for..in loop
The for..in loop takes an object as iterator, and iterates through the elements one at a time in the sequence. In each iteration an element is fetched and stored in the loop variable. When there is no more element in iterator, loop is terminated.
Syntax:

for(var loopVariable in iterator){
  //body of loop
}
Enter fullscreen mode Exit fullscreen mode

Example:

var list = [1, 2, 3, 4];
for(var element in list){
  print(element);
}
Enter fullscreen mode Exit fullscreen mode

Output:

1
2
3
4
Enter fullscreen mode Exit fullscreen mode

3. while loop
The while loop will execute a block of statement as long as a test expression is true.
Syntax:

while(condition) {
  //body of loop
}
Enter fullscreen mode Exit fullscreen mode

Example:

int count = 4;
int i = 0;
while(i < count) {
  print(i);
  i++;
}
Enter fullscreen mode Exit fullscreen mode

Output:

0
1
2
3
Enter fullscreen mode Exit fullscreen mode

4. do..while loop
The do…while statement executes loop statements and then test the condition for next iteration and executes next only if condition is true.

int count = 4;
int i = 0;
do{
  print(i);
  i++;
}while(i < count);
Enter fullscreen mode Exit fullscreen mode

Output:

0
1
2
3
Enter fullscreen mode Exit fullscreen mode

Functions
Functions are block of reusable code that are used to peform a single related action. Function may or may not take inputs and may or may not return an output. Dart is a true object-oriented language, so even functions are objects and have a type, Function. This means that functions can be assigned to variables or passed as arguments to other functions.

Syntax:

returntype name(parameters) {
  //body
}
Enter fullscreen mode Exit fullscreen mode

Example:

bool isEligibleToVote(int age){
return age >= 18;
}
bool result = isEligibleToVote(16);
bool result2 = isEligibleToVote(21);
print(result);
print(result2);
Enter fullscreen mode Exit fullscreen mode

Output:

false
true
Enter fullscreen mode Exit fullscreen mode

If function does not return anything, use void as return type.

Although Dart recommends type annotation, function would still work if you omit the return type.

For functions that contain just one expression, you can use a shorthand syntax:
bool isEligibleToVote(int age) => age >= 18;
is equivalent to

bool isEligibleToVote(int age) {
  return age >= 18;
}
Enter fullscreen mode Exit fullscreen mode

Parameters
A function can have any number of required positional parameters. These can be followed either by named parameters or by optional positional parameters (but not both).
Positional paramters Example:

int sum(int a, int b,[int c]) {
  return a + b + (c ?? 0);
}
print(sum(1, 3, 5));
print(sum(1, 3));
Enter fullscreen mode Exit fullscreen mode

Output:

9
4
Enter fullscreen mode Exit fullscreen mode

Here a and b are required positional parameters while c in optional positional parameters.
[] represents optional positional parameters.

Named parameters
Named parameters are optional unless they’re specifically marked as required.
When defining a function use{type1 param1, type2 param2,...} to specify named parameters.
When calling a function, you can specify named parameters using paramName: value. For example:

void display({String name, int age}) {
 print('$name is $age years old.');
}
display(name: 'Mark', age: 16);
Enter fullscreen mode Exit fullscreen mode

Output:

Mark is 18 years old.
Enter fullscreen mode Exit fullscreen mode

Although named parameters are a kind of optional parameter, you can annotate them with @required to indicate that the parameter is mandatory — that users must provide a value for the parameter. For example:

void display({String name, @required int age}) {
 print('$name is $age years old.');
}
Enter fullscreen mode Exit fullscreen mode

To use the @required annotation, depend on the meta package and import package:meta/meta.dart.

Default parameters value
Your function can use = to define default values for both named and positional parameters. The default values must be compile-time constants. If no default value is provided, the default value is null.
void enableFlags({bool bold = false, bool hidden = false}) {...}

String say(String from, String msg,
    [String device = 'carrier pigeon']) {
  var result = '$from says $msg with a $device';
  return result;
}
print(say('Bob', 'Hello'));
Enter fullscreen mode Exit fullscreen mode

Output:

Bob says Hello with a carrier pigeon.
Enter fullscreen mode Exit fullscreen mode

The main() function
Every app must have a top-level main() function, which serves as the entrypoint to the app. The main() function returns void and has an optional List<String> parameter for arguments.
Example:

void main() {
  print('Hello world from main function.');
}
Enter fullscreen mode Exit fullscreen mode

Output:

Hello world from main function.
Enter fullscreen mode Exit fullscreen mode

Anonymous functions
You can also create a nameless function called an anonymous function. An anonymous function looks similar to a named function— zero or more parameters, separated by commas and optional type annotations, between parentheses.
([[Type] param1[, …]]) {
//body of function
};

Example:

var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
  print('${list.indexOf(item)}: $item');
});
Enter fullscreen mode Exit fullscreen mode

Output:

0: apples
1: bananas
2: oranges
Enter fullscreen mode Exit fullscreen mode

Here
(item) {
print('${list.indexOf(item)}: $item');
})
is anonymous function. It is executed for each element of the list. Anonymous function can also be assigned to a variable.

List.forEach() function
The forEach() method receives a function as an argument and executes it once for each array element. It returns null.
Example:

var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
  print('${list.indexOf(item)}: $item');
});
Enter fullscreen mode Exit fullscreen mode

Output:

0: apples
1: bananas
2: oranges
Enter fullscreen mode Exit fullscreen mode

List.map() function
The map method receives a function as a parameter. Then it applies it on each element and returns an new Iterable populated with the results of calling the provided function. This Iterable can be converted to list by calling toList() method on it.
Example:

var list = [1, 2, 3];
var squaredList = list.map((i) {
  return i * i;
}).toList();
print(squaredList);
Enter fullscreen mode Exit fullscreen mode

Output:

[1, 4, 9]
Enter fullscreen mode Exit fullscreen mode

Cascade notation (..)
Cascades .. allow you to make a sequence of operations on the same object. In addition to function calls, you can also access fields on that same object. This often saves you the step of creating a temporary variable and allows you to write more fluid code.
Example:

var list = [1, 2, 3, 4];
list
  ..add(5)
  ..add(6)
  ..first = 2;
print(list);
Enter fullscreen mode Exit fullscreen mode

Output:

[2, 2, 3, 4, 5, 6]
Enter fullscreen mode Exit fullscreen mode

Here list.add(5) method is applied on list which adds 5 at the end of list, then list.add(6) method is applied on list which adds 6 at the end of list and at last list.first = 2 which makes first element as 2.

list.first is used to retrieve or change first element of list. Simliarly, list.last is used to retrieve or change last element of list.

Classes
Dart is an object-oriented language with classes and mixin-based inheritance. Every object is an instance of a class and all classes descend from Object.
A class can be created using class keyword.
Example :

class Point {
...
}
Enter fullscreen mode Exit fullscreen mode

Instance variables
Here how declare instance variable:

class Point {
  double x;
  double y;
}
Enter fullscreen mode Exit fullscreen mode

All uninitialized instance variables have the value null.

Constructors
Declare a constructor by creating a function with the same name as its class. Constructors are generally used to initialize instance variable of a class:

class Point {
  double x, y;

  Point(double x, double y) {
    // There's a better way to do this, stay tuned.
    this.x = x;
    this.y = y;
  }
}
Enter fullscreen mode Exit fullscreen mode

The this keyowrd is used to refer to current instance of the class.

The pattern of assigning a constructor argument to an instance variable is so common, Dart has syntactic sugar to make it easy:

class Point {
  double x, y;
  Point(this.x, this.y);
}
Enter fullscreen mode Exit fullscreen mode

Named constructor
Use a named constructor to implement multiple constructors for a class or to provide extra clarity:

class Point {
  double x, y;

  Point(this.x, this.y);

  // Named constructor
  Point.origin() {
    x = 0;
    y = 0;
  }
}
Enter fullscreen mode Exit fullscreen mode

Initializer list
You can initialize instance variables before the constructor body runs. Use : after constructor parameter list to use initializer and separate initializers with commas.
Example:

class Point {
  double x, y;

  Point(this.x, this.y);

  // Named constructor
  Point.origin() {
    x = 0;
    y = 0;
  }

  //Initializer list
  Point.fromJson(Map<String, dynamic> parsedJson) :
    this.x = parsedJson['x']
    this.y = parsedJson['y'] {
    //body of the constructor
  }
}
Enter fullscreen mode Exit fullscreen mode

Methods
Functions defined within class which represents a specify purpose are called methods. Methods of a class have access to instance variables and this.
The distanceTo() method in the following sample is an example of an instance method:

import 'dart:math';

class Point {
  double x, y;

  Point(this.x, this.y);

  double distanceTo(Point other) {
    var dx = x - other.x;
    var dy = y - other.y;
    return sqrt(dx * dx + dy * dy);
  }
}
Enter fullscreen mode Exit fullscreen mode

import keyword is used to import objects and methods from other packages like built-in packages or from other files. In this example we are importing sqrt() function from dart:math package.

Instance of a class
Instance of a class can be created by calling constructor the class. This instance contains property and methods of the class. Those property and methods can be accessed using . operator.
Example:

import 'dart:math';

class Point {
  double x, y;

  Point(this.x, this.y);

  double distanceTo(Point other) {
    var dx = x - other.x;
    var dy = y - other.y;
    return sqrt(dx * dx + dy * dy);
  }
}
void main() {
  Point point = Point(2.0, 4.0);
  Point point2 = Point(2.0, 6.0);
  print(point2.x);
  print(point2.y);
  print(point2.distanceTo(point));
}
Enter fullscreen mode Exit fullscreen mode

Output:

2.0
6.0
2.0
Enter fullscreen mode Exit fullscreen mode

Unlike some other languages, new keyword is optional while creating instance of a class.

Static variables
Static variables (class variables) are useful for class-wide state and constants:

class Point {
  static const originX= 0.0;
  static const originY = 0.0;
  //...
}
Enter fullscreen mode Exit fullscreen mode

Static methods
Static methods (class methods) don’t operate on an instance, and thus don’t have access to this ie. they can access current instance properties. They do, however, have access to static variables. They can be accessed directly from class without the need of creating an instance.
Example:

class Point {
  double x, y;
  static const originX= 0.0;
  static const originY = 0.0;

  Point(this.x, this.y);

  static String currentOrigin() {
    return 'Current origin: ($originX, $originY)';
  }
}
void main() {
  print(Point.currentOrigin());
}
Enter fullscreen mode Exit fullscreen mode

Output:

Current origin: (0.0, 0.0)
Enter fullscreen mode Exit fullscreen mode

Public and Private members
Properties and methods of a class are public, meaning they can be accessed from outside class using instance of the class.
Example:

class Point {
  double x, y;

  Point(this.x, this.y);
}
void main() {
  Point point = Point(3.0, 6.0);
  print(point.x);
  print(point.y);
}
Enter fullscreen mode Exit fullscreen mode

Output:

3.0
6.0
Enter fullscreen mode Exit fullscreen mode

If you want to make an property or method as private, use _ before property or method name. Unlike other languages, here private doesn't mean it is available only to the class it is in, private means it is available in the library.

Getters and setters
Getters and setters are special methods that provide read and write access to an object’s properties. Getters are used to read an object's properties while setters are set an object property. Each instance variable has an implicit getter, plus a setter if appropriate. You can create additional properties by implementing getters and setters, using the get and set keywords:

class Point {
  double _x, _y;

  Point(this._x, this._y);

  double get xCoordinate => this._x;
  double get yCoordinate => this._y;

  void set XCoordinate(double x) => this._x = x;
  void set YCoordinate(double y) => this._y = y;
}
void main() {
  Point point = Point(3.0, 6.0);
  point.XCoordinate = 4.0;
  point.YCoordinate = 8.0;
  print(point.xCoordinate);
  print(point.yCoordinate);
}
Enter fullscreen mode Exit fullscreen mode

Output:

4.0
8.0
Enter fullscreen mode Exit fullscreen mode

Inheritance
Like any other object oriented language, Dart supports inheritance. A class can inherits from other class. Class which inherits are called child class or subclass and class which is being inherited is called parent or super class. Subclass inherits all the property of the parent class.
Inheritance is achieved using extends keyword.
In the coming flutter tutorials, you will quite often come across example like this:

import 'package:flutter/material.dart';
class Home extends StatelessWidget {
  ...
}
Enter fullscreen mode Exit fullscreen mode

Here Home class is inheriting properties and methods from StatelessWidget class defined in package:flutter/material.dart package.

Method overriding
You can override method defined in parent class by defining method with same name and parameter list as the method in parent class. You can use the @override annotation to indicate that you are intentionally overriding a member:

import 'package:flutter/material.dart';
class Home extends StatelessWidget
{
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}
Enter fullscreen mode Exit fullscreen mode

Here we are overriding build(BuildContext context) method defined in parent class ie. StatelessWidget class.

Enumerated types
Enumerated types, often called enumerations or enums, are a special kind of class used to represent a fixed number of constant values.

Using enums
Declare an enumerated type using the enum keyword:

enum Color { red, green, blue }
Each value in an enum has an index getter, which returns the zero-based position of the value in the enum declaration. For example, the first value has index 0, and the second value has index 1.
To get a list of all of the values in the enum, use the enum’s values constant.
Example:

enum Color { red, green, blue}
void main() {
  List<Color> colors = Color.values;
  print(colors);
  print(Color.red.index);
  print(Color.green.index);
  print(Color.blue.index);
}
Enter fullscreen mode Exit fullscreen mode

Output:

[Color.red, Color.green, Color.blue]
0
1
2
Enter fullscreen mode Exit fullscreen mode

Assert
During development, use an assert statement — assert(condition, optionalMessage); — to disrupt normal execution if a boolean condition is false.

String text;
assert(text != null, 'Text is null');
Enter fullscreen mode Exit fullscreen mode

Output:

Failed assertion: line 3 pos 10: 'text != null': Text is null
Enter fullscreen mode Exit fullscreen mode

In production code, assertions are ignored, and the arguments to assert aren’t evaluated.

Exception
Your Dart code can throw and catch exceptions. Exceptions are errors indicating that something unexpected happened. You can raise manually using throw keyword.
throw Exception('this is a sample exception')

Exception handling
Exception handling is an important part of development because unhadled exception can break an app. Exception handling allows you to handled those exception before any harm is done.
In Dart, exception handling is done using try..catch statement.

try statement
In try block, we generally put lines of code which may result in exception.

catch statement
Catching, or capturing, an exception stops the exception from propagating (unless you rethrow the exception). Catching an exception gives you a chance to handle it:

int x = 8;
int y = 0;
try {
  res = x ~/ y; 
  print(res);
} on IntegerDivisionByZeroException { 
  print('Cannot divide by zero'); 
} catch (e) {
  print('Other types of exception');
}
Enter fullscreen mode Exit fullscreen mode

Output:

Cannot divide by zero
Enter fullscreen mode Exit fullscreen mode

use on keyword to accept exception of a specific type while catch (e) without any specific exception catches all types of exception.

Finally
To ensure that some code runs whether or not an exception is thrown, use a finally clause.

try {
  //Code that may result in exception.
} catch (e) {
  // Handle the exception first.
} finally {
  // Then clean up.
  //This code always runs irrespective of whether any exception occured or not.
}
Enter fullscreen mode Exit fullscreen mode

We are going to use exception handling a lot when we will be trying fetch data from internet or when trying to access a device functionality like gps or camera.

Reference
Most of the example in the tutorial can be found on [Official Dart Language Tour] page(https://dart.dev/guides/language/language-tour). You can refer that page for an even more in-depth tutorial of the language.

Conclusion

So this was a comprehensive tour of the dart language. I tried to cover up most of the concepts, we will be frequently using in the series. This tutorial can also be used as a guide or reference for the future.
This was quite a long tutorial, so in inadvertently some errors or typos may have crept in the tutorial. I would very much appreciate, if someone can point out those errors and typos.

So you all in the next tutorial which will be

Basics of Flutter

Thank you and Goodbye👋👋.
Goodbye

Top comments (1)

Collapse
 
bigfidelis profile image
Oluborode Akintunde Paul

Nice write-up, so descriptive 👍