-
Notifications
You must be signed in to change notification settings - Fork 1
Basics of Dart and OOP
Dart is an open-source general-purpose programming language. It is originally developed by Google. Dart is an object-oriented language with C-style syntax. It supports programming concepts like interfaces, classes, unlike other programming languages Dart doesn’t support arrays. Dart collections can be used to replicate data structures such as arrays, generics, and optional typing.
The following code shows a simple Dart program −
void main() {
print("Dart language is easy to learn");
}
The main()
function is a predefined method in Dart. It is the most important and mandatory part of any Dart Program. Any Dart script requires the main() method for its execution. This method acts as the entry point for any Dart application. It is responsible for executing all library functions, user-defined statements, and user-defined functions.
void main()
{
//main() function body
}
Variable is named storage location and Data types simply refers to the type and size of data associated with variables and functions.
Dart uses var keyword to declare the variable. The syntax of var is defined below,
var name = 'Dart';
The final and const keyword are used to declare constants. They are defined as below −
void main() {
final a = 12;
const pi = 3.14;
print(a);
print(pi);
}
Dart language supports the following data types −
- Numbers - It is used to represent numeric literals – Integer
int
and Doubledouble
. - Strings - It represents a sequence of characters. String
String
values are specified in either single or double quotes - Booleans - Dart uses the
bool
keyword to represent Boolean values –true
andfalse
. - Lists and Maps - It is used to represent a collection of objects. A simple
List
can be defined as below −
void main() {
var list = [1,2,3,4,5];
print(list);
}
Map
can be defined as shown here −
void main() {
var mapping = {'id': 1,'name':'Dart'};
print(mapping);
}
- Dynamic − If the variable type is not defined, then its default type is
dynamic
. The following example illustrates the dynamic type variable −
void main() {
dynamic name = "Dart";
print(name);
}
A decision making block evaluates a condition before the instructions are executed. Dart supports if
, if..else
and switch
statements.
Loops are used to repeat a block of code until a specific condition is met. Dart supports for
, for..in
, while
and do..while
loops.
Let us understand a simple example about the usage of control statements and loops −
void main() {
for( var i = 1 ; i <= 10; i++ ) {
if(i%2==0) {
print(i);
}
}
}
The above code prints the even numbers from 1 to 10.
Functions are the building blocks of readable, maintainable, and reusable code. A function is a set of statements to perform a specific task. Functions organize the program into logical blocks of code. Once defined, functions may be called to access code. This makes the code reusable. Moreover, functions make it easy to read and maintain the program’s code.
A function declaration tells the compiler about a function's name, return type, and parameters. A function definition provides the actual body of the function. Let us look into a simple function in Dart as shown here −
void main() {
add(3,4);
}
void add(int a,int b) {
int c;
c = a+b;
print(c);
}
The above function adds two values and produces 7 as the output.
Lambda functions are a concise mechanism to represent functions. These functions are also called as Arrow functions. Syntax-
[return_type]function_name(parameters)=>expression;
Example:
void main() {
printMsg();
print(test());
}
printMsg()=>
print("hello");
int test()=>123;
// returning function
Object-oriented programming combines a group of data attributes with functions or methods into a unit called an "object." Typically, OOP languages are class-based, which means that a class defines the data attributes and functions as a blueprint for creating objects, which are instances of the class.
A simple example would be a class representing a person. The person class would contain attributes to represent information such as the person’s age, name, height, etc. The class definition might also contain functions such as "sayMyName" which would simply print that person’s name to the screen.
class Person{
// attributes
int age;
String name;
double height;
// constructor
Person(String name){
this.name = name;
}
// method or fucntion
void sayMyName(){
print("My name is $name");
}
}
A family could be constructed by instantiating person objects from the class for each member of the family. Each person object would contain different data attributes since each person is unique.
void main(){
Person p1 = Person("Praveen");
p1.sayMyName();
// prints `My name is Praveen`
}
This programming style is pervasive in popular programming languages such as Java, C++, Python, JavaScript and C# among others. By defining sets of classes that represent and encapsulate objects in a program, the classes can be organized into modules, improving the structure and organization of software programs.
Dart is an object-oriented programming language, and it supports all the concepts of object-oriented programming such as classes, object, inheritance, mixin, and abstract classes. As the name suggests, it focuses on the object and objects are the real-life entities. The Object-oriented programming approach is used to implement the concept like polymorphism, data-hiding, etc.
We use class
keyword to create a class in Dart. Instance Variables and Instance Methods live on the object. this
keyword inside an instance method points to the object itself, hence we can access a property of the object.
A Class is a user-defined data type that describes the characteristics and behavior of it. To get all properties of the class, we must create an object of that class. The syntax of the class is given below.
class ClassName {
<fields>
<getter/setter>
<constructor>
<functions>
}
A constructor is an instance method that is invoked when an object is created from the class. This is a good place to initialize instance variables. A constructor function has the same name as the class.
// simple Persona class with constructor
class Person {
// instance variables with `null` value
String firstName, lastName;
// instance variable with `null` value
int age;
// constructor function
Person( String firstName, String lastName, [ int age = 18 ] ) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
// instance methods
String getFullName() {
return this.firstName + " " + this.lastName; // `this` points to the object itself
}
}
Usage in main( )
/**
* A constructor function of the class is implicitly called by the Dart when an object is created from it.
* The default constructor method has the same name as the class.
*
* A constructor function is generally used to initialize instance variables,
* with values passed by the user while creating an object.
*/
void main() {
// create `p1` object
Person p1 = new Person( 'Praveen', 'Varma' );
print( "Full name: ${ p1.getFullName() }" );
print( "Age: ${ p1.age }" );
}
In the above example, our constructor function Person needs two required positional arguments while age has a default 18 value. Dart provides a shorthand syntax for a constructor function to set instance variables.
Person( this.firstName, this.lastName, [ this.age = 18 ] );
This is the preferred way to write a constructor whose only job is to set initial values to the instance variables. Optional parameters must have a default value, else null
will be set by the constructor even if the default value was given in instance variable declaration in the class.
Dart provides multiple constructors on a class. Apart from default constructors, other constructors must have a name. While creating an object from a class, we need to use the name named constructor.
/**
* Dart supports having multiple constructor functions in a class.
* But only one default constructor function is allowed which will be called implicitly.
* Other constructor function must be registered with `MyClass.constructorName() {}` syntax.
*
* While creating an object, we can specify a constructor function using below syntax.
* -> var obj = new MyClass.constructorName();
*
* When it comes to a constructor function whose only job is to initialize instance variables,
* Dart provides an easier syntax to write default or named constructor function.
* -> MyClass( this.instVarOne, this.instVarTwo, [ this.instVarThree = 'DefaultVal' ] );
*/
void main() {
// create `p1` object
Person p1 = Person.initWithUpperCase( 'Praveen', 'Varma' );
print( "Full name: ${ p1.getFullName() }" );
}
// simple Person class with multiple constructor functions
class Person {
// instance variables with `null` value
String firstName, lastName;
// instance variable with `null` value
int age;
// default constructor function
Person( this.firstName, this.lastName, [ this.age = 18 ] );
// named constructor: initWithUpperCase
Person.initWithUpperCase( String firstName, String lastName, [ int age = 18 ] ) {
this.firstName = firstName.toUpperCase();
this.lastName = lastName.toUpperCase();
this.age = age;
}
// instance methods
String getFullName() {
return this.firstName + " " + this.lastName;
}
}
Apart from the name, there is no difference between default and named constructors. We can also use the shorthand instance variable assignment syntax for the named constructors as well.
A combination of the getter and the setter methods are used to transform and/or encapsulate instance variables. In Dart, the getter is an instance method specified by get
keyword. This method does not take any arguments, hence it does not contain parentheses ()
. While the setter method is specified by set
keyword which receives value to be set as an argument.
/**
* A getter function is called when it is accessed like an instance variable on the object.
* A setter function is called when a value is assigned to object with the same variable name.
*
* We use `get` keyword to define a `getter` function.
* Getter function does not take any arguments and returns a value.
* Hence getter function does not have parentheses. They can also be fat-arrow functions for simplicity.
* -> String get funcName { return_statement; }
* -> String get funcName => return_statement;
*
* We use `set` keyword to define a `setter` function.
* A setter function takes one arguments which is the value user is trying to set and returns no value (void).
* -> void set funcName () { statements; }
* -> void set funcName => statement;
*/
void main() {
var p1 = Person( "Praveen Varma" );
print( p1.fullName );
// change name
p1.fullName = "Alan Walker";
print( p1.fullName );
}
class Person {
// _ (underscore) prefix makes variables private to the library
String _firstName, _lastName;
// default constructor
Person( String name ) {
var nameParts = name.split(" "); // split name by a space
this._firstName = nameParts[ 0 ];
this._lastName = nameParts[ 1 ];
}
// getter function for `fullName` property
String get fullName {
return "${ this._firstName } ${ this._lastName }";
}
// setter function for `fullName` property
void set fullName( String name ) {
var nameParts = name.split(" "); // split name by a space
this._firstName = nameParts[ 0 ];
this._lastName = nameParts[ 1 ];
}
}
In the above example, a getter can also be written using Fat Arrow function syntax like below but without any arguments.
String get fullName => "${ this._firstName } ${ this._lastName }";
An object is a real-life entity such as a table, human, car, etc. The object has two characteristics - state and behavior. Let's take an example of a car which has a name, model name, price and behavior moving, stopping, etc. The object-oriented programming offers to identify the state and behavior of the object.
We can access the class properties by creating an object of that class. In Dart, The object can be created by using a new keyword followed by class name. The syntax is given below.
var objectName = new ClassName(<constructor_arguments>)
Dart supports inheritance, which is used to create new classes from an existing class. The class that to be extended is called parent /superclass, and the newly created class is called child/subclass. Dart provides extends keyword to inherit the properties of parent class in child class. The syntax is given below.
class child_class_name extends parent_class_name
Example:
/**
* A Dart class can inherit instance variables and instance methods of another class.
* Using `extend` keyword, a class basically extends the properties and behaviours of another class.
*
* Apart from static properties and constructor functions, everything else is inherited.
* A class that is inherting another class is called sub-class while the class that it inherits from is called `super-class`.
*
* When a class is inheried, Dart provides `super` keyword in `sub-class` to point to `super-class`.
* `super` when used as a function calls the `default` constructor of the `super-class`.
* We use `super.namedConstructor()` syntax to call a named constructor of the `super-class`.
* A `sub-class` can access instance methods of the `super-class` using `super.methodName` syntax.
*
* When a `super-class` constructor function or method is called from the `sub-class`,
* `this` object inside those functions is still pointing to the `sub-class` object.
*/
void main() {
// create an Employee object
var e = Employee( 'Ross', 'Geller', 1000 );
print( 'Employee e : ${ e.firstName } ${ e.lastName }, salary: ${ e.salary }' );
// create Student object
var s = Student( 'Praveen', 'Varma', 418 );
print( 'Student s : ${ s.firstName } ${ s.lastName }, salary: ${ s.score }%' );
// create Person object
var p = Person( 'Alan', 'Walker' );
print( 'Person p : ${ p.firstName } ${ p.lastName }' );
}
// [super-class]
// Person class with basic details
class Person {
String firstName, lastName;
// default constructor
Person( this.firstName, this.lastName );
// named constructor
Person.withUpperCase( String firstName, String lastName ) {
this.firstName = firstName.toUpperCase();
this.lastName = lastName.toUpperCase();
}
}
// [sub-class]
// Employee class shares feature of Person class
class Employee extends Person {
int salary;
// default constructor calls the default constructor of `Person` class using `super` function
// constructor of the `Person` is executed first before the constructor of the `Employee` class
// arguments of the `sub-class` default constructor function are available in `super` call
Employee( String firstName, String lastName, this.salary ): super( firstName, lastName );
}
// Student class shares feature of Person class
class Student extends Person {
num score;
// default constructor calls `Person.withUpperCase` constuctor function of `Person` class
Student( String firstName, String lastName, num marks ): super.withUpperCase( firstName, lastName ) {
this.score = num.parse( ( (marks / 500) * 100 ).toStringAsFixed( 6 ) ); // limit decimal places to 2
}
}
When we inherit a class, its methods are also available on the sub-class. The super()
function calls the super-class constructor and super
keyword points to the super-class. We can also call super-class instance methods using super.superClassMethod()
syntax.
This is an overview of Object Oriented Programming in Dart which is required for Flutter development, and ofcourse there is much more to learn, as OOP in general, itself is one of the vast and amazing concepts of programming!