Object Oriented Concepts of Dart Programming Language – @Dart Basics

Object Oriented Concepts of Dart Programming Language – @Dart Basics

In this tutorial, I will talk about the Object Oriented Concepts of Dart Programming Language. As previously stated; Dart is statically typed object oriented language; will have look on the object oriented components of language in this tutorial. If you need a beginner introduction to the language please refer to my previous article here.

Constructor Functions

It may appear weird that you may generate an instance of a class (i.e., an object) by invoking it like a function.
That makes more sense once you realize that each class has a specific method that you may (but don’t have to) add to it (if you don’t, the class has an empty default method): The function Object() method is used to create a new object.
Here’s how you would add a constructor to Person:

class Person { 
String name; int age;

Person(String name, int age) { 
this.name = name; // this.name refers to the “name” property
this.age = age; 
} 
void greet() {
print('Hi, I am ' + name + ' and I am ' + age.toString() + ' years old!'; 
} 
}

A function Object() method is created by duplicating the class name within the class and writing it as if it were a regular class method (without a return type though).
The function Object() can (but is not required to) accept parameters that you can utilize in the function Object() body. These parameters are usually used to set up various class properties (in this example name and age). Using such a function Object() has the benefit of allowing you to create many, individually configured instances of this class, all of which are based on the same class but have distinct name and age values.

var mySelf = Person('John', 25); 
var someoneElse = Person('James', 40);

When we have to class properties with the identical names, it might be unclear because the function Object() requires two inputs, name and age.
It’s critical to realize that Dart features a notion known as “Scoping.” Inside the function Object() method, it scopes (= “limits the usage”) the name and age provided as parameters. You can only use name and age in the function Object() method, for example.

However, on a class level, names and ages are visible to the whole class. You may use this to tell them apart. To make it obvious that you’re talking about class-level attributes, use name and this.age. Dart believes you’re referring to local (method-level) variables named name and age if you don’t use the special this keyword.
There can be several function Object() methods in a class! You can specify as many “utility constructors” (not an official word) as you like, which are generally used to produce different pre-configured instances of a class:

class Person { 
String name; 
int age;

Person(String name, int age) { 
this.name = name; // this.name refers to the “name” property
this.age = age; 
}

Person.sixty(String name) { 
this.name = name;
this.age = 60; // not configured dynamically! 
}

void greet() { 
print('Hi, I am ' + name + ' and I am ' + age.toString() + ' years old!'; 
}
}

Constructors can also be reduced if they just accept arguments and allocate them to class properties. By utilizing the aforementioned shortcut (no function Object()body, ; after the function Object() this. in front of the argument, no types being used, arguments matching property names), you tell Dart to automatically store the argument values in the class’s appropriate properties.

Positional & Named Arguments

You may always take two sorts of arguments: positional and named parameters, whether you’re dealing with function Object() methods, regular methods, or normal functions.
We’ve only used positional arguments so far (in the examples above), which means the first value you put into the function when calling it is passed into the first parameter. The second argument receives the second value, and so on.
You may also utilize named parameters, which are very handy if your functions have a lot of arguments. It might be tough to remember the position of each parameter (when calling the function) – utilizing names can help, especially because IDEs like Visual Studio Code can assist you with completion.

void doSomething({String name, double price, String description}) { ... }

In this example, name, price and description are named arguments – simply by wrapping the argument list with { }.

Inheritance

Returning to the subject of classes and objects. When working with Flutter, you’ll come across the term “inheritance” frequently.
The term “inheritance” refers to a class’s ability to be based on another class (but only one other class, not many classes).

class Person {
void greet() {
print('Hi!');
}
}


class Friend extends Person {
void greetFriendly() {
print('Good to see !');
}
}


void main() {
var myFriend = Friend();
myFriend.greet(); // works and prints “Hi”
myFriend.greetFriendly(); // also works and prints “Good to see !”
}

Friend is a class that inherits from Person in this example (using the extend keyword). The Friend class now contains all of the attributes and methods of the Person class, but it may also add its own. You can use anything you can on a Person instance on a Friend instance, plus you can, of course, use all of Friend’s capabilities. Every instance of Friend is both of type Friend and of type Person by default!
You may also override base/parent class methods (and properties):

class Friend extends Person {
@override
void greet() {
print('Hello there!');
}


void greetFriendly() {
print('Good to see !');
}
}

Using @override is recommended (technically, it’s not required though) because it makes it quite apparent that you are overriding a base class method on purpose (and not by mistake).

Throwing a bonus of final and const type of variables

final & const

Dart knows three types of variables/ properties:
1. “Real variables” (created via var or the type name)
2. Final variables (created via final, final + type name when creating uninitialized variables)
3. Constants (created via const)

The distinction between “real variables” (a word I coined; it isn’t an official one) and final or constant variables should be obvious: “Real variables” can alter their values, but final or constant variables cannot.
This causes an error for example:

final myName = 'John'; 
myName = 'James';

Dart would object to the re-assignment of a final variable.
If you don’t plan to alter variables, it’s a good idea to designate them as final. This is a scenario you’ll see a lot in Flutter projects.

But what is the difference between final and const?

Const values are compile-time constants, while final values are runtime constants.
That implies you don’t have to know the precise end number while you’re creating the code. For example, a value submitted by a user of the app may not change in the future (i.e. it is final), but you are unaware of this when writing the app’s code.
Const values, on the other hand, are known at the time the code is written.
For example, some text you wish to display in a widget may not change at runtime and therefore is a compile-time constant.

const title = 'Your Products’; // this can’t change at runtime!