OOP Paragidm
OOP uses objects and their interactions to design and program
Learning Objectives
- To understand KEY WORDS in object-oriented programming.
- To understand paradigms of OOP.
- Introduce Factory Methods in OOP
- Introduce Singletons in OOP
- Explain what Mixins are in OOP
OOP In Dart
Object-oriented programming (OOP) is a programming method that uses objects and their interactions to design and program applications. It is one of the most popular programming paradigms and is used in many programming languages, such as Dart, Java, C++, Python, etc.
In OOP, an object can be anything, such as a person, a bank account, a car, or a house. Each object has its attributes (or properties) and behavior (or methods). For example, a person object may have the attributes name, age and height, and the behavior walk and talk.
Advantages
- It is easy to understand and use.
- It increases reusability and decreases complexity.
- The productivity of programmers increases.
- It makes the code easier to maintain, modify and debug.
- It promotes teamwork and collaboration.
- It reduces the repetition of code.
Features Of OOP
- Class
- Object
- Encapsulation
- Inheritance
- Polymorphism
- Abstraction
Key Points
- Object Oriented Programming (OOP) is a programming paradigm that uses objects and their interactions to - design and program applications.
- OOP is based on objects, which are data structures containing data and methods.
- OOP is a way of thinking about programming that differs from traditional procedural programming.
- OOP can make code more modular, flexible, and extensible.
- OOP can help you to understand better and solve problems.
Classes
In object-oriented programming, a class is a blueprint for creating objects. A class defines the properties and methods that an object will have. For example, a class called Dog might have properties like breed, color and methods like bark, run.
Declaring A class in Dart
In Dart programming, you can declare a class using the class keyword followed by the class name. Here’s a simple example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Declaring a class in Dart
class Person {
// Properties of the class
String name;
int age;
// Constructor
Person(this.name, this.age);
// Method to display person details
void displayInfo() {
print('Name: $name, Age: $age');
}
}
- Class Declaration
- The class keyword is used to declare a class, followed by the class name Person.
Objects
An object is an instance of a class. It represents a real-world entity with attributes (properties) and behaviors (methods). Objects allow you to create multiple instances of a class, each with its own unique data.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// Declaring a simple class in Dart
class Car {
String brand;
String model;
Car(this.brand, this.model);
void showDetails() {
print('Brand: $brand, Model: $model');
}
}
void main() {
// Creating an object of the Car class
Car myCar = Car('Toyota', 'Corolla');
// Calling the method using the object
myCar.showDetails(); // Output: Brand: Toyota, Model: Corolla
}
- Class Declaration
- The Car class has two properties: brand and model.
- The constructor Car(this.brand, this.model); initializes these properties.
- Object Creation
- Car myCar = Car(‘Toyota’, ‘Corolla’);
- creates an object myCar of the Car class with specific values for brand and model.
Object Oriented Programming Paradigm
Data Encapsulation
Data encapsulation is the process of keeping a class’ implementation details hidden from the user through an object’s functions.
How To Achieve Encapsulation In Dart
Encapsulation can be achieved by:
- Declaring the class properties as private by using underscore(_).
- Providing public getter and setter methods to access and update the value of private property.
Getter and Setter Methods
Getter and setter methods are used to access and update the value of private property. Getter methods are used to access the value of private property. Setter methods are used to update the value of private property.
Code sample
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class Circle {
// Private property with underscore (_)
double _radius;
// Constructor to initialize the radius
Circle(this._radius);
// Getter method to access the private radius
double get radius => _radius;
// Setter method to update the radius with validation
set radius(double value) {
if (value > 0) {
_radius = value;
} else {
print('Radius must be greater than 0');
}
}
// Method to calculate area of the circle
double calculateArea() {
return 3.1416 * _radius * _radius; // Area = πr²
}
}
void main() {
// Creating an instance of Circle
Circle circle = Circle(5.0);
// Accessing the radius using getter
print("Initial radius: ${circle.radius}");
// Calculating and printing the area
print("Initial area: ${circle.calculateArea()}");
// Updating the radius using setter
circle.radius = 7.0;
// Accessing updated radius and area
print("Updated radius: ${circle.radius}");
print("Updated area: ${circle.calculateArea()}");
// Trying to set an invalid radius
circle.radius = -3.0; // This will trigger validation
}
Explanation
- The Circle class has a private variable _radius, which is not directly accessible from outside the class.
- The constructor initializes the _radius variable.
- Getter (get radius) allows external code to access the value of _radius.
- Setter (set radius) provides controlled access to update the value of _radius with validation.
The calculateArea method demonstrates how methods can use the encapsulated data.
Inheritance
Generally speaking, inheritance is the process of gaining properties. OOP allows for the inheritance of properties from one object to another.
Code sample
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// Base class (Superclass)
class Vehicle {
String brand;
int year;
// Constructor for Vehicle
Vehicle(this.brand, this.year);
// Method to display vehicle info
void displayInfo() {
print("Brand: $brand");
print("Year: $year");
}
}
// Derived class (Subclass) inheriting from Vehicle
class Car extends Vehicle {
String model;
// Constructor for Car which uses super to call the base class constructor
Car(String brand, int year, this.model) : super(brand, year);
// Method to display car-specific info
void displayCarInfo() {
displayInfo(); // Call the base class method
print("Model: $model");
}
}
void main() {
// Creating an instance of the Car class
Car car = Car('Toyota', 2021, 'Corolla');
// Accessing methods from both base and derived classes
car.displayCarInfo();
}
Explanation
- The Vehicle class is the base class with instance variables brand and year, and a method displayInfo.
- The Car class is the derived class that extends (inherits from) the Vehicle class. It adds an additional property model and a method displayCarInfo.
- The Car constructor uses super to call the constructor of the base class (Vehicle).
- The main function demonstrates creating an instance of the Car class and accessing methods from both the base and derived classes.
Polymorphism
Polymorphism is the practice of having many classes use the same method name while redefining it for the derived classes.
Code sample
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// Base class
class Animal {
// Method to be overridden by derived classes
void makeSound() {
print("Animal makes a sound");
}
}
// Derived class Dog that overrides makeSound method
class Dog extends Animal {
@override
void makeSound() {
print("Dog barks");
}
}
// Derived class Cat that overrides makeSound method
class Cat extends Animal {
@override
void makeSound() {
print("Cat meows");
}
}
void main() {
// Creating instances of Animal, Dog, and Cat
Animal animal = Animal();
Dog dog = Dog();
Cat cat = Cat();
// Calling makeSound method for each instance
animal.makeSound(); // Calls Animal's version
dog.makeSound(); // Calls Dog's version
cat.makeSound(); // Calls Cat's version
}
Explanation
- The Animal class is the base class with a method makeSound.
- The Dog and Cat classes are derived classes that override the makeSound method with their own implementations.
- In the main function, instances of Animal, Dog, and Cat are created.
- The makeSound method is called on each object, demonstrating polymorphism as the appropriate version of the method is invoked based on the actual type of the object.
Abstraction
Abstraction refers to the user’s interaction with just a subset of an object’s characteristics and operations. To access a complicated item, abstraction uses simpler, high-level techniques.
1
2
- Simple items are used to show complexity.
- Keep complicated information hidden from the user.
Simple classes are used to indicate complexity in abstraction. Encapsulation is an extension of abstraction.
Advantages of Abstraction
- It simplifies the process of seeing things in their entirety.
- Code duplication is avoided, and reusability is increased.
- Because just the most necessary information is shown to the user, it helps to enhance the security of an application or software.
Code example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// Abstract class Shape
abstract class Shape {
// Abstract method (no implementation)
double calculateArea();
// Concrete method (with implementation)
void printInfo() {
print("This is a shape.");
}
}
// Concrete class Circle extends Shape
class Circle extends Shape {
double radius;
// Constructor for Circle
Circle(this.radius);
// Override the abstract method to provide specific implementation
@override
double calculateArea() {
return 3.14 * radius * radius;
}
}
// Concrete class Rectangle extends Shape
class Rectangle extends Shape {
double width;
double height;
// Constructor for Rectangle
Rectangle(this.width, this.height);
// Override the abstract method to provide specific implementation
@override
double calculateArea() {
return width * height;
}
}
void main() {
// Create instances of Circle and Rectangle
Circle circle = Circle(5.0);
Rectangle rectangle = Rectangle(10.0, 20.0);
// Using the common interface provided by the Shape abstract class
circle.printInfo(); // Calls the concrete method in the abstract class
print("Circle Area: ${circle.calculateArea()}");
rectangle.printInfo(); // Calls the concrete method in the abstract class
print("Rectangle Area: ${rectangle.calculateArea()}");
}
Explanation
- The Shape class is an abstract class with an abstract method calculateArea() and a concrete method printInfo().
- The Circle and Rectangle classes are concrete classes that extend the Shape class and provide implementations for the abstract method.
- In the main function, instances of Circle and Rectangle are created and used through the common interface provided by the Shape abstract class.