Skip to content

Latest commit

 

History

History

Dart

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

Dart Notes

The notes here has been taken from the handwritten notes of Kamal Sharma's Telegram channel and can be found here.


Dart

Dart is the main programming language to develop cross-platform mobile application using flutter framework


Contents:

  • Setup
  • Fundamental
  • Data Types
  • String
  • Type Conversion
  • Constant
  • Null
  • Operators
  • Loop
  • Collection [list, set, Map]
  • Function
  • Class
  • Exceptional Handling

How to run Dart Code:

dart <filename>.dart

Install dart extension in Microsoft Visual Studio

Dart is a static type programming language. It is also a compiled programming language

Static type means if you defined a variable as a string, you cannot assign other values like integer (or) double on that string type.

Dart supports two types of compilation: ADT, JIT

  1. AOT - Ahead of time
  2. JIT - Just in time

When we have to run a dart program, we have to compile it then run. It happens automatically. When we write a dart program, and run it, it automatically compiles on the fly. This is called just in time compilation.

When we deploy our final product, then it will be compiled as AOT complication with some optimization.


Fundamentals

Every Dart program starts with a main() function.

main() {
    var firstName = 'Leo';
    String lastName = 'Valdez';
    print(firstName + lastName);
}

when you define variables with var keyword, Dart automatically detects the type based on the value assigned. This is called type inference.

Dart supports both: type interface and statically type defined.

All the built in dart libraries like collection, and other core functions are defined in a package. That is called dart:core package.

syntax to import:

import 'dart:core';

The dart:core package is automatically imported for most dart programmers.

For user-input stuff, we have to import dart:io.

main() {
    stdout.writeln('What is your name? ')
    String name = stdin.readLineSync();
    print('My name is $name');
}

$name - String interpolation

// - In-line comment

/*
Block comment
*/

/// - Documentation


Data Types

There are 2 types of available is strongly typed language: The type of a variable is known at compile time. For example C++, Java, Swift.

Dynamically Typed Language: The type of a variable is known at run time.
For example: Python, Ruby, JavaScript

In Dart programming language, there are 5 basic types:

  • int
  • double
  • String
  • bool
  • dynamic

After a data-type is assigned using var and the type is recognized, then you can't assign a new type later.

Eg:

var a = 10;
a = 'Hello'; //It will return error

Dart is an OOP language and everything is an object in here.

Even the null type is an object.

Even the function [main()] is also an object which is the subtype of the function class.


String, type conversion, constant, null

String can be either in '' or "".

In '', you have to use \ to print special characters

But in " " you can use one single quote.

var S3 = 'It\'s easy!';
var S4 = "It's funny";

To define a raw string, put a r in front of the string.
i.e, if a \n is there, then it won't be evaluated. I think it applies to all whitespace characters.

Let's say you want to print a string without any formatting, then at that time you can prefix it with a r in the front.

Example:

void main() {
  var S3 = r"It\'s \n easy!";
  var S4 = "It\'s \n easy!";
  print('String 3 -  $S3');
  print('String 4 - $S4');
}
Output
String 3 -  It\'s \n easy!
String 4 - It's
 easy!

String Interpolation

String interpolation means to replace a variable's value with an actual value within a string.

main() {
    var age = 25;
    var str = 'My age is: $age';
    print(str);
}

Multiline string

we can define multiline string in dart either by using 3 single quotes in the beginning and end (or) by using 3 double quotes.

main() {
    var s1 = '''
    you can create
    multi-line string
    like this one''';
    print(s1);
}

Type conversion

It is an important concept in any programming language.

To convert string to integer value, user parse().

var one = int.parse('1');
assert(one == 1);

Sometimes we need to convert a string to an integer and vice versa.

To convert a string to an integer value, you can use the parse() method of int object.

main() {
    // String -> int
    var one = int.parse('1');
    assert(one == 1);

    // String -> double
    var onePeriodOne = double.parse('1.1');
    assert(onePeriodOne == 1.1);
}

If you try to convert a trying with alphabets to integers. you will get FormatException error.


Converting to string

toString()

main() {
    // int -> String
    String oneAsString = 1.toString();
    assert(oneAsString == '1.1');

    // double -> String
    String piAsString = 3.14159.toStringAsFixed(2);
    assert(piAsString == '3.14');
}

Constant variable

To define a constant variable in dart, use the keyword const.

main() {
    const aConstNum = 0;
    const aConstBool = true;
    const aConstString = 'a constant string';

    print(aConstNum)
    print(aConstBool)
    print(aConstString)

    print(aConstNum.runtimeType);
    print(aConstBool.runtimeType);
    print(aConstString.runtimeType);
}

By type interface, the compiler will assign the data types to the variables.

main() {
    int num;
    print(num);
}

Output

null

We can also specify null

main() {
    int num = null;
    print(num);
}

Output

null

Operators

All the standard operators from C, C++, Java, and Swift will also work in dart programming language.

void main() {
    int num = 10+22;
    num = num-2;
    print(num);

    num = num % 5;
    print(num);

    // relational ==, !=, >=, <=, <, >
    if(num == 0) {
        print('Zero');
    }

    num = 100;
    num *= 2;

    // != Not equal
    if(num != 100) {
        print('num is not equal');
    }

    //unary operators
    ++num;
    num++;
    num += 1;
    num == 1;
    print(num);

    //logical operator: &&, ||, !
    if(num > 200 && num < 203) {
        print('200 to 202');
    }
}

Null aware operator ?., ??, ??=

It is one of the important operator in dart language. These operators are common in modern programming languages such as Swift, Kotlin.
In Dart, There are 3 variables of this operators.

Suppose we want to define a class

class Num {
    int num = 10;
}

main() {
    var n = Num(); // To create  object
    int number = 1;

    if(n!==null) {
        number = n.num;
    }
    print(number)
}

Output:

10

We can check null in another method

number = n?.num;

this line will replace:

if(n!==null) {
number = n.num;
}

What that line will do?

If n is a valid object then access the property name num and assign its value to number.
If n is a null object, then skip this.

main() {
    number = n?.num ?? 0;
    print(number);
}
number = n?.num ?? 0;

When this is null, this will be executed. Kind of like assigning a default value for null objects.

??=

This will assign a value if the object is null.

    int n;
    print(n??=100);
    print(n);

Output

100

Ternary Operator

void main() {
    int x = 100;
    var result = x % 2 == 0 ? 'Even' : 'Odd';
    print(result);
}

Output

Even

Type Test Operator

void main() {
    var x = 100;
    if(x is int) {
        print('Integer');
    }
}

Conditional Statements

void main() {
  int number = 100;

  // If else ladder
  if (number % 2 == 0) {
    print('Even');
  } else if (number % 3 == 0) {
    print('Odd');
  } else {
    print('Confused');
  }

  // Switch Case

  switch (number) {
    case 0:
      print('Even');
      break;
    case 1:
      print('Odd');
      break;
    default:
      print('Confused');
  }
}

Looping Statement:

void main() {
  //Standard  for loop
  for (var i = 1; i <= 10; ++i) {
    print(i);
  }

  // For in loop
  var numbers = [1, 2, 3];
  for (var n in numbers) {
    print(n);
  }

  // Standard way of accessing it.
  for (var i = 0; i < numbers.length; i++) {
    print(numbers[i]);
  }

  // forEach loop method 1
  numbers.forEach((n) => print(n));

  // forEach loop method2
  numbers.forEach(printNum);

  // while loop
  int num = 5;
  while (num > 0) {
    print(num);
    num -= 1;
  }

  // do while loop
  do {
    print(num);
    num += 1;
  } while (num < 5);
}

void printNum(num) {
  print(num);
}

Break and Continue

void main() {
  // example for break
  for (var i = 0; i < 10; i++) {
    if (i > 5) break;
    print(i);
  }

  // example for continue
  for (var j = 0; j < 10; j++) {
    if (j % 2 == 0) continue;
    print('Odd: $j');
  }
}

Collections

There are 3 built-in collection types in Dart Language:

  • Lists
  • Sets
  • Maps

List: Ordered collection of values

In some programming languages it is called array, but in Dart programming language. It is called list.

One way to define list is by using List class

List names = ['Jack', 'Jill'];

Copying a list to another variable

  var names2 = names1;

It will not copy the list.
Here, the names2 will be like a reference to names 1.
Just like how it is in Python.
So, We will use spread operator to copy. (...)

  List<String> games = ['TT', 'Chess'];
  var games2 = [...games];
  games[1] = 'Football';
  for (var game in games2) {
    print(game);
  }

Set: Unordered collection of unique items.

// Set  Method 1
  var halogens = {'Fluorine', 'Chlorine', 'Fluorine'};
  for (var element in halogens) {
    print(element);
  }

  // Set Method 2
  Set<String> friends = {'Ross', 'Chandler'};
  for (var friend in friends) {
    print(friend);
  }

To define a empty set:

Set<String> hobbies = {};
print(hobbies.runtimeType);

Map

In Dart Programming Language, Map is a collection of (key -> value) pair of items

In python, It is known as dictionary

// Map Method 1

var gifts = {
// Key : Value
'first': 'Patridge',
'second': 'Turtledoves',
'third': 'Golden Rings'
};
print(gifts['second']);

//Map Method 2
var folklore = Map();

folklore['first'] = 'the 1';
folklore['second'] = 'cardigan';
print(folklore);

Functions

In Dart Programming Language, each function is an object of class function.

Syntax:

returnType FunctionName(argList) {

    Statements_1;
    Statements_2;

    return <data>
}

Arrow function (=>)

Short way to define a function
Example

dynamic square(var n) => n*n;

Anonymous Function

A function with no name is called Anonymous function in Dart Programming Language.

In python, It is known as Lambda Function.

void main() {
  showOutput(square(3));
  showOutput(square1(3.5));

  print(square1.runtimeType);

  var list = ['apples', 'bananas', 'oranges'];

  //wkt, forEach function takes a function as argument
  list.forEach(printF);

  //now, lets try to make a anonymous function
  list.forEach((item) {
    print(item);
  });
}

void printF(item) {
  print(item);
}

dynamic square(var num) {
  return num * num;
}

// Arrow function =>
dynamic square1(var num) => num * num;

void showOutput(var msg) {
  print(msg);
}

There are 2 types of parameters in dart programming language:

  • Positional Parameter/Argument
  • Named Parameter/Argument

Named Parameter

When you are using named parameter, you have to specify the name of the parameter when you are calling the function.

This is applicable for both: arrow & general function.

void main() {
    print(sum(num2:4, num1:2));
    dynamic sum({var num1, var num2}) => num1 + num2;
}

By default named parameter is optional and, we can also mix positional and named parameter together.

void main()  {
    print(sum(10));
}
//method 1
dynamic sum(var num1, {var num2}) => num1 + (num ?? 0);
// default
dynamic sum(var num1, {var num2 = 0}) => num1 + (num ?? 0);
// Positional Optional
dynamic sum(var num1, [var num2]) => num1 + (num ?? 0);

Class

Blueprint for an actual object

class Person {
  String name;
  int age;

  // Constructor

  Person(String name, [int age = 18]) {
    this.name = name;
    this.age = age;
  }

  // Person(this.name, [this.age = 18]); is also a constructor

  // named constructor
  Person.guest() {
    name = 'Guest';
    age = 10;
  }

  void showOutput() {
    print(name);
    print(age);
  }
}

void main() {
  Person person1 = Person('Leo', 24);

  // person1.name = 'Leo';
  // person1.age = 20;

  // person1 = Person.guest(); is possible.
  Person p2 = Person.guest();
  Person p3 = Person('Jason');

  person1.showOutput();
  p2.showOutput();
  p3.showOutput();
}

Static, Final, Const


Final

For data members
when you want to assign the value only once and want it to be fixed, use final

There are two ways to define a constant:

  • Using final keyword
  • Using Const keyword

There's a difference in both ways
In const, it happens at compile time and once assigned it cannot be reassigned

In final within the class the value gets assigned at runtime. So, it can be changed using the constructor

If you want to use a constant value using a constructor within a class, you have to put static in front of the const variable.

So, when you use static it becomes the property of the class rather than the object. static property is same for all objects.

To access static variable

className.<staticVariableName>

You can use final and const outside classes too.

class X {
  final name; // type will be defined by inferred value
  static const int age = 24;

  X(this.name);
}

main() {
  var x = X('jack');
  print(x.name);

  print(X.age); // to access static object

  var y = X('Jill');
  print(y.name);

  // You can use final and const out of a class too
  final artistName = 'Lauv';
  const albums = 2;

  print(artistName);
  print(albums);
}

Inheritance

In dart, we use the extends keyword to implement inheritance.

class Vehicle {
  String model;
  int year;

  Vehicle(this.model, this.year) {
    print(this.model);
    print(this.year);
  }

  void showOutput() {
    print(model);
    print(year);
  }
}

class Car extends Vehicle {
  double price;

  Car(String model, int year, this.price) : super(model, year);

  void showOutput() {
    super.showOutput();
    print(this.price);
  }
}

void main() {
  var car1 = Car('Accord', 2014, 150000);
  car1.showOutput();
}

Method Overriding

Suppose in a class there is a class method and in the sub class there is a method with the same name and we want to redefine it, it is called method overriding.

If we want to let other programmers to know that this method is overriding, you can use @override notation.

When you use @override, above a method signature, that means that the compiler will know that this method is overriding.

Incase there is no method of the original name, it will show an error.
i.e, If in desired, a method is defined with @override and there is no method in base class with the same name, then it shows error like "Method doesn't override an inherited method".

This is basically a safety feature in Dart. when you are overriding a method, if you do not use the @override keyword, it would not show an error. There is no issue for this.

You have to use @override when you don't have control of super class method implementation.

Basically the intent of the @override notation is to catch situation when a super class method renames.


A member on an independent subclass which used to override the member could continue silently working with the superclass implementation.

So, a good practice would be to use @override when you override a superclass method.

class X {
  String name;

  X(this.name);

  void showOutput() {
    print(this.name);
  }

  dynamic square(dynamic val) {
    return val * val;
  }
}

class Y extends X {
  Y(String name) : super(name);

  @override
  void showOutput() {
    print(this.name);
    print('Hello');
  }

  //not using @override at this time
  dynamic square(dynamic val) {
    print(val);
    return val * val;
  }
}

void main() {
  Y y1 = Y('Leo');
  y1.showOutput();
  var k = y1.square(2);
  print(k);
}

Getter and Setters

They are special methods that provide read and write access to an object's properties.

Normally, each instance variable has an implicit getter plus setter if appropriate but if you want you can create additional property by implementing getters and setters using the get and set keyword

num -> it is a type inherited from Integer and Double

When we have to call a method. we use () parenthesis but when we are using the getter or setter, we do not need to use parenthesis.

When we want to access any getter, we have to use the dot operator and we want to use the setter, we have to call the setter name with an assignment operator

class Rectangle {
  num left, top, width, height;

  Rectangle(this.left, this.top, this.width, this.height);

  //Define two calculated properties: right and bottom
  num get right => left + width;
  set right(num value) => left = value - width;
  num get bottom => top + height;
  set bottom(num value) => top = value - height;
}

void main() {
  var rect = Rectangle(3, 4, 20, 15);
  print(rect.left);
  rect.right = 12;
  print(rect.left);
}

Exception Handling:

throw, catch, try, finally

To thrown exception, you have to use throw keyword and exception class name and within the exception class name you can provide a message

int mustBeGreaterThanZero(int val) {
  if (val <= 0) {
    throw Exception('Value must be greater than zero');
  }
  return val;
}

void letsVerifyTheValue(var val) {
  var valueVerification;

  try {
    valueVerification = mustBeGreaterThanZero(val);
  } catch (e) {
    print(e);
  } finally {
    if (valueVerification == null) {
      print('Value is not accepted');
    } else {
      print('Value verifed: $valueVerification');
    }
  }
}

void main() {
  letsVerifyTheValue(10);
  letsVerifyTheValue(0);
}