# Dart Programming Language

Heyy fellow techies!!!

Presuming you're already having some idea about Java or C++, I'd like to introduce Dart to you.

It's actually very easy if you have done any object oriented language before but even if you're a beginner, feel free to go through the blog as I have made things simple.

There are no restrictions.

I have covered almost everything I guess. But even if I missed something you can reach out to me and inform me.

That'd be of some great help.

I have prioritised more on the code part because it makes easier to understand stuff.

So let's get started!!!

Dart was developed by Google. It is a scalable language (i.e. used to write large programs) and is used all over the world for building applications and is used in the most popular frontend framework i.e. Flutter. Be it mobile, web or server-side applications and command line scripts. With the help of dart, it is quite easy to do such things.

**Note:** *Go through the code sample properly if you wanna learn with full efficiency. It contains important definitions which need to be properly understood by you.*

## Syntax

```plaintext
void main(){
    print("Hi");
    print('Hi');
    // this is a comment
    // ends with semicolon
}

Output: Hi
        Hi
        (both are the same)
```

## Data Types

All data types in Dart are objects. Therefore their initial value is defined as null.

(int, double, Strings, boolean, Lists, Maps, Runes, Symbols)

```plaintext
int a = 1; 
var a = 2;

double d = 3.3;
var d = 3.4;

String s = "abc";
var s = "xyz";

bool b = true;
var b = false; 

// var automatically reads value and determines which data type you're using.
```

## Literals

We can assign literals to some variables eg. int x = 2.

int = datatype, x = variable, 2 = Literal. (could be Strings, double etc)

## Escape Character ('\\')

String s = 'It\\'s easy'

(makes it recognizable because it's confusing)

## String Interpolation('$')

```plaintext
// We use '+' in Java and C++ to add something in print statements.
// In Dart, we use $

String s1 = "Sanzu";
String s2 = "Name: $s1";
String s3 = "${s1.length}"
```

## Final and Static keyword

final: As the name suggests, when you initialize a value add final to it so that you can't change it afterwards. (means it's the final value of that variable and it's value can't be changed afterwards on further lines of code)

const: It's just like final, but is compiled during compilation.

# Conditional Statements:

## i) If-Else

```plaintext
if(condition){
      //code
} else {
      //code
}
```

## ii) If Else-If (multiple conditions)

```plaintext
if(condition 1){
      //code
} else if (condition 2){
      //code
} else if (condition 3){
      //code
} else {
      //code
}
```

## iii) Switch case (only works for int and String)

```plaintext
String grade = 'A';
	switch (grade){
		case 'A':
			print("Excellent");
			break;

		case 'B':
			print("Very Good");
			break;

		case 'C':
			print("Good enough. But work hard");
			break;

		case 'D':
			print("You barely pass");
			break;

        case 'E':
			print("You have failed");
			break;

		default:
			print("Enter a valid Grade");
	}
}
```

# Loops:

## i) for

```plaintext
for (int i = 1; i <= 10; i++) {
		if ( i % 2 == 0) {
			print(i);
		}
}
```

## ii) for in

```plaintext
List expressions = ["hello", "hi", "bye"];
	for (String s in expressions) {
		print(s);
	}
}
```

## iii) Nested for

```plaintext
for (int i=1; i <= 10; i++) {
   for (int j=1; j <= 10; j++) { 
		// any condition
   }
}
```

## iv) while

```plaintext
int i = 1;
	while (i <= 10) {
		if (i % 2 == 0) {
			print(i);
		}
		i++;
	}
```

## v) do while

```plaintext
int i = 1;
	do {
		if ( i % 2 == 0) {
			print(i);
		}
		i++;
	} while ( i <= 10);
```

## Break and Continue

We use this to break outside our loop. In flutter, we have a special functionality which is: we can break any loop just by calling it.

```plaintext
myOuterLoop: for (int i = 1; i <= 3; i++) {
	innerLoop: for (int j = 1; j <= 3; j++) {
		print("$i $j");
		if (i == 2 && j == 2) {
			break myOuterLoop;
		}
	}
}

// continue - the loop skips the condition where continue is there and the         further the iteration is continued.
```

## Functions

```plaintext
void main() {
	findPerimeter(4, 2);
	int rectangleArea = getArea(10, 5);
	print("The area is $rectangleArea");
}

void findPerimeter(int l, int b) {
	print(2*(l+b));
}

int getArea(int l, int b) {
	return l*b;
}

// function - main() - 0 arguments
//            findPerimeter(int l, int b) - 2 arguments 
//            getArea(int l, int b) - 2 arguments
// arguments are something that we pass after a function
// just see and code and try to figure out how are we passing the values, data types and arguments.
```

## Fat Arrow ('=&gt;')

```plaintext
void main() {
    print('hi'):
}
// can also be written as
void main() => print('hi');
```

## Exception Handling

An exception is an error that takes place inside the program. When an exception occurs inside a program the normal flow of the program is disrupted and it terminates.

Many expections can be passed using clauses.

```plaintext
// 1. ON Clause
// 2. Catch Clause with Exception Object
// 3. Catch Clause with Exception Object and StackTrace Object
// 4. Finally Clause
// 5. Create our own Custom Exception

void main() {
	// CASE 1: When you know the exception to be thrown, use ON Clause
	try {
		int result = 12 ~/ 0;
		print("The result is $result");
	} on IntegerDivisionByZeroException {
		print("Cannot divide by Zero");
	}

	// CASE 2: When you do not know the exception use CATCH Clause
	try {
		int result = 12 ~/ 0;
		print("The result is $result");
	} catch (e) {
		print("The exception thrown is $e");
	}

	// CASE 3: Using STACK TRACE to know the events occurred before Exception was thrown
	try {
		int result = 12 ~/ 0;
		print("The result is $result");
	} catch (e, s) {
		print("The exception thrown is $e");
		print("STACK TRACE \n $s");
	}

	// CASE 4: Whether there is an Exception or not, FINALLY clause is always executed
	try {
		int result = 12 ~/ 3;
		print("The result is $result");
	} catch (e) {
		print("The exception thrown is $e");
	} finally {
		print("This is FINALLY Clause and is always executed.");
	}

	// CASE 5: Custom Exception
	try {
		depositMoney(-200);
	} catch (e) {
		print(e.errorMessage());
	} finally {
		// Code
	}
}
```

## Class, Objects and Reference variables

```plaintext
void main() {

	var student1 = Student(); // One Object, student1 is reference variable
	student1.id = 23;
	student1.name = "Peter";
	print("${student1.id} and ${student1.name}");

	student1.study();
	student1.sleep();

}

class Student {
	int id = -1; 			// Instance or Field Variable, default value is -1
	String name;  		// Instance or Field Variable, default value is null

	void study() {
		print("${this.name} is now studying");
	}

	void sleep() {
		print("${this.name} is now sleeping");
	}
}
```

## Constructors

```plaintext
void main() {

	var student1 = Student(23, "Peter");// One obj, student1 is reference var
	print("${student1.id} and ${student1.name}");

	student1.study();
	student1.sleep();
}

class Student {
	int id = -1;
	String name;

	Student(this.id, this.name);    // Parameterised Constructor

	Student.myAnotherNamedConstructor(this.id, this.name);  // Named Constructor

	void study() {
		print("${this.name} is now studying");
	}

	void sleep() {
		print("${this.name} is now sleeping");
	}
}
```

## Getters and Setters

```plaintext
void main() {

  var student = Student();
  student.name = "Peter";     // set value
  print(student.name);        // get value

  student.percentage = 438.0;   // set value
  print(student.percentage);    // get value
}

class Student {
  String name;       
  double percent;    
  void set percentage(double marksSecured) => percent = (marksSecured / 500) * 100;
  double get percentage => percent;
}
```

## Inheritance

Process of getting properties of another class.

```plaintext
void main() {

	var dog = Dog();
	dog.breed = "Labrador";
	dog.color = "Black";
	dog.bark();
	dog.eat();

	var cat = Cat();
	cat.color = "White";
	cat.age = 6;
	cat.eat();
	cat.meow();

	var animal = Animal();
	animal.color = "brown";
	animal.eat();
}

class Animal {
	String color;
	void eat() {
		print("Eat !");
	}
}

class Dog extends Animal {      // Dog is Child class or sub class, Animal is                            super or parent class
	String breed;
	void bark() {
		print("Bark !");
	}
}

class Cat extends Animal {      // Cat is Child class or sub class, Animal is super or parent class
	int age;
	void meow() {
		print("Meow !");
	}
}
```

## Method Overriding

Allows a method in a child class to override the same method in the parent class. In

```plaintext
void main() {

	var dog = Dog();
	dog.eat();

	print(dog.color);Animal = parent class.                    Dog = child class
```

## Abstraction

the class which contain one or more than 1 abstract method

```plaintext
void main() {

//	var shape = Shape();        // Error. Cannot instantiate Abstract Class

	var rectangle = Rectangle();
	rectangle.draw();

	var circle = Circle();
	circle.draw();
}

abstract class Shape {

	// Define your Instance variable if needed
	int x;
	int y;
	void draw();        // Abstract Method
	void myNormalFunction() {
		// Some code
	}
}

class Rectangle extends Shape {
	void draw() {
		print("Drawing Rectangle.....");
	}
}

class Circle extends Shape {
	void draw() {
		print("Drawing Circle.....");
	}
}
```

## Interface

Simply pointing out similarities among unrelated class.

```plaintext
void main() {

	var tv = Television();
	tv.volumeUp();
	tv.volumeDown();
}

class Remote {

	void volumeUp() {
		print("______Volume Up from Remote_______");
	}

	void volumeDown() {
		print("______Volume Down from Remote_______");
	}
}

// Here Remote acts as Interface
class Television implements Remote, AnotherClass {

	void volumeUp() {
//		super.volumeUp();       // Not allowed to call super while implementing a class as Interface
		print("______Volume Up in Television_______");
	}

	void volumeDown() {
		print("______Volume Down in Television_______");
	}

	void justAnotherMethod() {
		print("Some code");
	}
}
```

## Static Methods

It is used for method that is the same for every instance of a class, this means if a data type is static, it can be accessed without creating an object.

```plaintext
void main() {

	var circle1 = Circle();
//	circle1.pi;     // 4 bytes

	var circle2 = Circle();
//	circle2.pi;     // 4 bytes

	// 8 bytes      // waste of extra 4 bytes

	Circle.pi;  // 4 bytes
	Circle.pi;  // No more memory will be allocated .


//	circle.calculateArea();

//	print(Circle.pi);           // Syntax to call Static Variable

//	Circle.calculateArea();     // Syntax to call Static Method
}

class Circle {

	static const double pi = 3.14;
	static int maxRadius = 5;

	String color;

	static void calculateArea() {
		print("Some code to calculate area of Circle");
//		myNormalFunction();     // Not allowed to call instance functions
//		this.color;             // You cannot use 'this' keyword and even cannot access Instance variables
	}

	void myNormalFunction() {
		calculateArea();
		this.color = "Red";
		print(pi);
		print(maxRadius);
	}
}
```

## Lambda Expressions aka Arrow Functions

```plaintext
void main() {

	// Defining Lambda: 1st way
	Function addTwoNumbers = (int a, int b) {
		var sum = a + b;
		print(sum);
	};

	var multiplyByFour = (int number) {
		return number * 4;
	};

	// Defining Lambda: 2nd way: Function Expression: Using Short Hand Syntax or FAT Arrow ( '=>' )
	Function addNumbers = (int a, int b) => print(a + b);

	var multiplyFour = (int number) => number * 4;


	// Calling lambda function
	addTwoNumbers(2, 5);
	print(multiplyByFour(5));

	addNumbers(3, 7);
	print(multiplyFour(10));
}


// A example of Normal function
void addMyNumbers(int a, int b) {

	var sum = a + b;
	print(sum);
}
```

## Lexical Closure

A closure is a function that has access to the parent scope, even after the scope has closed.

A closure is a function object that has access to variables in its lexical scope, even when the function is used outside of it's original scope.

```plaintext
void main() {

	String message = "Dar is good";

	Function showMessage = () {
		message = "Dart is awesome";
		print(message);
	};

	showMessage();

	Function talk = () {
		String msg = "Hi";
		Function say = () {
			msg = "Hello";
			print(msg);
		};
		return say;
	};
	Function speak = talk();
	speak();        // talk()     // say()      //  print(msg)    // "Hello"
}
```

# Bunch of remaining data types:

## Lists

### i) fixed

```plaintext
void main() {
    List<int> numbersList = List(5);        // Fixed-length list
	numbersList[0] = 73;  // Insert operation
	numbersList[1] = 64;
	numbersList[3] = 21;
	numbersList[4] = 12;

	numbersList[0] = 99;  // Update operation
	numbersList[1] = null;// Delete operation

	print(numbersList[0]);
	print("\n");

//	numbersList.remove(73);                 // Not supported in fixed-length list
//	numbersList.add(24);                    // Not supported in fixed-length list
//	numbersList.removeAt(3);                // Not supported in fixed-length list
//	numbersList.clear();                    // Not supported in fixed-length list

	for (int element in numbersList) {                          // Using Individual Element (Objects)
		print(element);
	}

	print("\n");

	numbersList.forEach((element) => print(element));           // Using Lambda

	print("\n");

	for (int i = 0; i < numbersList.length; i++) {              // Using Index
		print(numbersList[i]);
	}
}
```

### ii) growable

```plaintext
void main() {
	// Elements:    N   21  12
	// Index:       0   1   2

	List<String> countries = ["USA", "INDIA", "CHINA"];     // Growable List : METHOD 1
	countries.add("Nepal");
	countries.add("Japan");


	List<int> numbersList = List();                         // Growable List: METHOD 2
	numbersList.add(73);    // Insert Operation
	numbersList.add(64);
	numbersList.add(21);
	numbersList.add(12);

	numbersList[0] = 99;    // Update operation
	numbersList[1] = null;  // Delete operation

	print(numbersList[0]);

	numbersList.remove(99);
	numbersList.add(24);
	numbersList.removeAt(3);
//	numbersList.clear();

	print("\n");

	for (int element in numbersList) {                  // Using Individual Element ( Objects )
		print(element);
	}

	print("\n");

	numbersList.forEach((element) => print(element));   // Using Lambda

	print("\n");

	for (int i = 0; i < numbersList.length; i++) {      // Using Index
		print(numbersList[i]);
	}

}
```

## Map and HashMap

```plaintext
void main() {

	Map<String, int> countryDialingCode = {         // Method 1: Using Literal 
		"USA": 1,
		"INDIA": 91,
		"PAKISTAN": 92
	};


	Map<String, String> fruits = Map();             // Method 2: Using Constructor
	fruits["apple"] = "red";
	fruits["banana"] = "yellow";
	fruits["guava"]  = "green";

	fruits.containsKey("apple");                        // returns true if the KEY is present in Map
	fruits.update("apple", (value) => "green");         // Update the VALUE for the given KEY
	fruits.remove("apple");                             // removes KEY and it's VALUE and returns the VALUE
	fruits.isEmpty;                                     // returns true if the Map is empty
	fruits.length;                                      // returns number of elements in Map
//	fruits.clear();                                     // Deletes all elements

	print(fruits["apple"]);

	print("\n");

	for (String key in fruits.keys) {           // Print all keys
		print(key);
	}

	print("\n");

	for (String value in fruits.values) {           // Print all values
		print(value);
	}

	print("\n");

	fruits.forEach((key, value) => print("key: $key and value: $value"));   // Using Lambda
```

## Set and HashSet

```plaintext
void main() {

	Set<String> countries = Set.from(["USA", "INDIA", "CHINA"]);     // Method 1: From a list
	countries.add("Nepal");
	countries.add("Japan");


	Set<int> numbersSet = Set();                                   // Method 2: Using Constructor
	numbersSet.add(73);     // Insert Operation
	numbersSet.add(64);
	numbersSet.add(21);
	numbersSet.add(12);

	numbersSet.add(73);     // Duplicate entries are ignored
	numbersSet.add(73);     // Ignored

	numbersSet.contains(73);        // returns true if the element is found in set
	numbersSet.remove(64);          // returns true if the element was found and deleted
	numbersSet.isEmpty;             // returns true if the Set is empty
	numbersSet.length;              // returns number of elements in Set
//	numbersSet.clear();             // Deletes all elements

	print("\n");

	for (int element in numbersSet) {                  // Using Individual Element ( Objects )
		print(element);
	}

	print("\n");

	numbersSet.forEach((element) => print(element));   // Using Lambda
}
```

## Callable class

User creates callable class which allows the instance of the class to be called as a function.

```plaintext
void main() {

	var personOne = Person();
	var msg = personOne(25, "Peter");
	print(msg);
}

class Person {
	
	String call(int age, String name) {
		return "The name of the person is $name and age is $age";
	}
}
```

---

That's all folks.

### Hope you had a great time learning.

## Thank you very much.
