Dart – 16 – Interfaces and Abstract Classes

Interfaces and Abstract Classes in Dart Programming

Interfaces and abstract classes are fundamental concepts in object-oriented programming (OOP), providing a way to define common behaviors and contracts that classes should adhere to. In Dart, a modern and expressive programming language, both interfaces and abstract classes play a significant role in creating flexible and extensible code. In this discussion, we’ll explore the significance of interfaces and abstract classes in Dart, understand how they work, and see practical examples of their use.

Understanding Interfaces

An interface in Dart defines a contract for classes that implement it. It specifies a set of methods that must be implemented by any class that adopts the interface. This ensures that objects of these classes share a common behavior, even though they may have different implementations.

Defining an Interface

In Dart, you can define an interface using an abstract class. An abstract class consists of abstract methods that only provide method signatures, without any implementation. Classes that implement the interface must provide concrete implementations of the interface methods.

Here’s an example of defining an interface using an abstract class in Dart:


abstract class Drawable {
    void draw();
}

class Circle implements Drawable {
    @override
    void draw() {
        print('Drawing a circle');
    }
}

class Rectangle implements Drawable {
    @override
    void draw() {
        print('Drawing a rectangle');
    }
}
    
Using Interfaces

Interfaces allow you to enforce a common behavior across different classes, making it easier to work with objects of diverse types that share the same interface. This simplifies code and promotes code reusability and modularity.

Here’s an example of using an interface in Dart:


void main() {
    var shapes = [
        Circle(),
        Rectangle(),
    ];

    for (var shape in shapes) {
        shape.draw();
    }
}
    

In this example, the Drawable interface is used to ensure that both Circle and Rectangle classes have a draw method. This allows us to create a list of drawable shapes and call the draw method on each of them.

Understanding Abstract Classes

Abstract classes in Dart serve a similar purpose as interfaces but can also contain instance variables and methods with default implementations. They provide a way to define a common structure and behavior that can be shared by subclasses.

Defining an Abstract Class

In Dart, you can define an abstract class using the abstract keyword. Abstract classes can contain both abstract (unimplemented) methods and concrete (implemented) methods.

Here’s an example of defining an abstract class in Dart:


abstract class Shape {
    double area(); // Abstract method
    void printInfo() {
        print('This is a shape.');
    }
}

class Circle extends Shape {
    double radius;

    Circle(this.radius);

    @override
    double area() {
        return 3.14 * radius * radius;
    }
}
    
Using Abstract Classes

Abstract classes allow you to define a common structure and behavior that can be inherited by subclasses. Subclasses must provide concrete implementations for the abstract methods while inheriting the concrete methods.

Here’s an example of using an abstract class in Dart:


void main() {
    var circle = Circle(5.0);
    circle.printInfo();
    print('Area: ${circle.area()}');
}
    

In this example, the Shape abstract class defines the area abstract method and the printInfo concrete method. The Circle class inherits from Shape and provides a concrete implementation for the area method.

Conclusion

Interfaces and abstract classes are essential concepts in Dart that allow you to define common behaviors, contracts, and structures for classes. They promote code reusability, maintainability, and modularity by enforcing a shared interface or behavior. Understanding how to use interfaces and abstract classes is crucial for designing flexible and extensible code in Dart.