What is Abstraction?
Abstraction in Dart refers to hiding the implementation details of a class and exposing only the essential features. It allows you to focus on what an object does rather than how it does it.
In Dart, abstraction is achieved using the abstract keyword. Abstract classes:
Can have both abstract methods (methods without implementation) and concrete methods (methods with implementation).
Cannot be instantiated directly (you cannot create objects from an abstract class).
Must be extended by other classes, which will provide implementations for the abstract methods.
Abstraction is another core principle of Object-Oriented Programming (OOP).
It involves simplifying complex systems by focusing on essential features and hiding unnecessary details.
It's about showing only the necessary information to the user and hiding the complex implementation.
In Summary
Abstraction is a crucial concept in OOP that allows you to create more maintainable, flexible, and reusable code by focusing on the essential aspects of objects and hiding their internal complexities.
Benefits of Abstraction
Reduced Complexity: Simplifies complex systems by hiding unnecessary details.
Increased Reusability: Enables you to write more generic and reusable code.
Improved Maintainability: Makes it easier to modify the implementation of a class without affecting other parts of the code.
Better Modularity: Promotes loose coupling between classes, leading to more modular and maintainable systems.
Simplifies Complex Systems: Hides unnecessary details from the user.
Improves Code Reusability: Shared behaviors can be defined once in the abstract class.
Enforces Consistency: Ensures that all subclasses implement required methods.
abstract class Shape {
double calculateArea();
}
class Circle implements Shape {
double radius;
Circle(this.radius);
@override
double calculateArea() {
return 3.14159 * radius * radius;
}
}
class Rectangle implements Shape {
double width;
double height;
Rectangle(this.width, this.height);
@override
double calculateArea() {
return width * height;
}
}
void main() {
Circle circle = Circle(5.0);
Rectangle rect = Rectangle(4.0, 3.0);
print('Circle Area: ${circle.calculateArea()}');
print('Rectangle Area: ${rect.calculateArea()}');
}
Explanation
Abstract Class:
The Shape class is declared as abstract.
An abstract class cannot be instantiated directly.
It defines a contract (the calculateArea() method) that all concrete (non-abstract) classes that inherit from it must implement.
Concrete Classes:
Circle and Rectangle are concrete classes that implement the Shape interface.
They provide their own specific implementations for the calculateArea() method.
Abstraction in Action:
The main function demonstrates how to use the Shape interface.
You can treat circle and rect as objects of the Shape type, even though they are instances of different concrete classes.
This abstraction allows you to work with shapes in a more generic way.
Here are 10 examples showcasing abstraction in Dart. Abstraction can be achieved by using abstract classes, which allow you to define abstract methods that must be implemented by subclasses. In Dart, abstract classes are defined with the abstract keyword.
A simple abstract class with an abstract method and a subclass implementing it.
abstract class Animal {
void makeSound();
}
class Dog extends Animal {
@override
void makeSound() {
print("Dog barks");
}
}
void main() {
Animal dog = Dog();
dog.makeSound(); // Output: Dog barks
}
Using abstraction to define an abstract method for calculating area in different shapes.
abstract class Shape {
double calculateArea();
}
class Circle extends Shape {
double radius;
Circle(this.radius);
@override
double calculateArea() {
return 3.1416 * radius * radius;
}
}
class Rectangle extends Shape {
double width, height;
Rectangle(this.width, this.height);
@override
double calculateArea() {
return width * height;
}
}
void main() {
Shape circle = Circle(5);
Shape rectangle = Rectangle(4, 6);
print("Circle Area: ${circle.calculateArea()}");
print("Rectangle Area: ${rectangle.calculateArea()}");
}
Using abstraction to define different payment methods.
abstract class Payment {
void processPayment(double amount);
}
class CreditCardPayment extends Payment {
@override
void processPayment(double amount) {
print("Processing credit card payment of \$${amount}");
}
}
class PaypalPayment extends Payment {
@override
void processPayment(double amount) {
print("Processing PayPal payment of \$${amount}");
}
}
void main() {
Payment creditPayment = CreditCardPayment();
Payment paypalPayment = PaypalPayment();
creditPayment.processPayment(100.0);
paypalPayment.processPayment(50.0);
}
Using abstraction to define different types of vehicles and how they start.
abstract class Vehicle {
void start();
}
class Car extends Vehicle {
@override
void start() {
print("Car starts with a key");
}
}
class Bike extends Vehicle {
@override
void start() {
print("Bike starts with a button");
}
}
void main() {
Vehicle car = Car();
Vehicle bike = Bike();
car.start();
bike.start();
}
Using an abstract class to calculate a bonus based on different employee types.
abstract class Employee {
double calculateBonus();
}
class Manager extends Employee {
double salary;
Manager(this.salary);
@override
double calculateBonus() => salary * 0.2; // 20% bonus
}
class Engineer extends Employee {
double salary;
Engineer(this.salary);
@override
double calculateBonus() => salary * 0.1; // 10% bonus
}
void main() {
Employee manager = Manager(5000);
Employee engineer = Engineer(4000);
print("Manager Bonus: \$${manager.calculateBonus()}");
print("Engineer Bonus: \$${engineer.calculateBonus()}");
}
Using abstraction to define different authentication types.
abstract class Authenticator {
void authenticate(String username, String password);
}
class EmailAuthenticator extends Authenticator {
@override
void authenticate(String username, String password) {
print("Authenticating $username with email.");
}
}
class PhoneAuthenticator extends Authenticator {
@override
void authenticate(String username, String password) {
print("Authenticating $username with phone.");
}
}
void main() {
Authenticator emailAuth = EmailAuthenticator();
Authenticator phoneAuth = PhoneAuthenticator();
emailAuth.authenticate("user1", "password123");
phoneAuth.authenticate("user2", "password456");
}
An abstract class to define different types of notifications.
abstract class Notification {
void send();
}
class EmailNotification extends Notification {
@override
void send() {
print("Sending email notification");
}
}
class SMSNotification extends Notification {
@override
void send() {
print("Sending SMS notification");
}
}
void main() {
Notification email = EmailNotification();
Notification sms = SMSNotification();
email.send();
sms.send();
}
An abstract class to define different types of data storage systems.
abstract class Storage {
void storeData(String data);
}
class LocalStorage extends Storage {
@override
void storeData(String data) {
print("Storing data locally: $data");
}
}
class CloudStorage extends Storage {
@override
void storeData(String data) {
print("Storing data in the cloud: $data");
}
}
void main() {
Storage local = LocalStorage();
Storage cloud = CloudStorage();
local.storeData("Local Data");
cloud.storeData("Cloud Data");
}
Using abstraction to define different file readers.
abstract class FileReader {
void readFile(String fileName);
}
class TextFileReader extends FileReader {
@override
void readFile(String fileName) {
print("Reading text file: $fileName");
}
}
class PDFFileReader extends FileReader {
@override
void readFile(String fileName) {
print("Reading PDF file: $fileName");
}
}
void main() {
FileReader textReader = TextFileReader();
FileReader pdfReader = PDFFileReader();
textReader.readFile("example.txt");
pdfReader.readFile("example.pdf");
}
Using an abstract class to define a calculation system with different types of calculations.
abstract class Calculator {
double calculate(double a, double b);
}
class Adder extends Calculator {
@override
double calculate(double a, double b) {
return a + b;
}
}
class Multiplier extends Calculator {
@override
double calculate(double a, double b) {
return a * b;
}
}
void main() {
Calculator adder = Adder();
Calculator multiplier = Multiplier();
print("Sum: ${adder.calculate(5, 3)}");
print("Product: ${multiplier.calculate(5, 3)}");
}