2 OOP Basic
2.1 Inheritance

Inheritance Pattern: The
Cat
andDog
classes inherit from theAnimal
superclass, demonstrating the “is-a” relationship.Abstract Class: I made
Animal
an abstract class since in the real world, you don’t instantiate a generic “animal” - you create specific types like cats or dogs.Key Implementation Details:
- The superclass
Animal
contains shared properties (name, sex, age, weight, color) and methods (breathe, eat, run, sleep) - Each subclass has its own specific properties:
Cat
hasisNasty
(boolean)Dog
hasbestFriend
(String, defaulting to “Human”)
- Each subclass has its own specific methods:
Cat
hasmeow()
Dog
hasbark()
- The superclass
Constructor Chaining: Both subclasses use the
super
constructor to initialize inherited properties from the Animal class.
This implementation demonstrates the Template Method Pattern implicitly - the superclass defines the structure and common behaviors, while subclasses can add their specific implementations and properties.
The example usage in the main()
function shows how both cats and dogs can use inherited methods (breathe, eat, run, sleep) while also having their unique behaviors (meow, bark) and properties.
2.2 Interface

// Interface definition (abstract class in Dart)
abstract class FlyingTransport {
// Interface method that must be implemented
void fly(String origin, String destination, int passengers);
}
// Helicopter class implementing FlyingTransport interface
class Helicopter implements FlyingTransport {
String model;
int maxAltitude;
{required this.model, this.maxAltitude = 15000});
Helicopter(
@override
void fly(String origin, String destination, int passengers) {
'Helicopter $model is flying from $origin to $destination');
print('Carrying $passengers passengers');
print('Flying at low altitude with vertical takeoff capability');
print(}
}
// Airplane class implementing FlyingTransport interface
class Airplane implements FlyingTransport {
String airline;
String flightNumber;
{required this.airline, required this.flightNumber});
Airplane(
@override
void fly(String origin, String destination, int passengers) {
'$airline Flight $flightNumber is flying from $origin to $destination');
print('Carrying $passengers passengers');
print('Cruising at high altitude on established flight path');
print(}
}
// DomesticatedGryphon class implementing FlyingTransport interface
class DomesticatedGryphon implements FlyingTransport {
String name;
int wingspan;
{required this.name, this.wingspan = 20});
DomesticatedGryphon(
@override
void fly(String origin, String destination, int passengers) {
'$name the Gryphon is flying from $origin to $destination');
print('Carrying $passengers brave passengers on its back');
print('Soaring majestically through the clouds');
print(}
}
// Airport class that uses FlyingTransport interface
class Airport {
String name;
String code;
List<FlyingTransport> scheduledFlights = [];
{required this.name, required this.code});
Airport(
// Accept method that takes any FlyingTransport implementation
void accept(FlyingTransport vehicle) {
'\n--- $name Airport ($code) ---');
print('Accepting flying transport for departure');
print(.add(vehicle);
scheduledFlights
// Airport can work with any FlyingTransport without knowing specific type
.fly(code, 'DEST', 50);
vehicle'Transport successfully departed from $name\n');
print(}
// Additional airport operations
void displaySchedule() {
'Total scheduled flights: ${scheduledFlights.length}');
print(}
}
// Example usage demonstrating the pattern
void main() {
// Create an airport
var jfkAirport = Airport(name: 'John F. Kennedy International', code: 'JFK');
// Create different flying transports
var helicopter = Helicopter(model: 'Bell 429');
var airplane = Airplane(airline: 'Delta', flightNumber: 'DL123');
var gryphon = DomesticatedGryphon(name: 'Goldwing', wingspan: 25);
// Airport accepts any FlyingTransport
// This demonstrates polymorphism through interfaces
.accept(helicopter);
jfkAirport.accept(airplane);
jfkAirport.accept(gryphon);
jfkAirport
// Display total scheduled flights
.displaySchedule();
jfkAirport
// Demonstrate that all types can be treated as FlyingTransport
'\n--- Direct Interface Usage ---');
print(List<FlyingTransport> vehicles = [
: 'Apache AH-64'),
Helicopter(model: 'United', flightNumber: 'UA456'),
Airplane(airline: 'Stormfeather')
DomesticatedGryphon(name
];
for (var vehicle in vehicles) {
.fly('LAX', 'ORD', 30);
vehicle'');
print(}
}
I’ll implement this UML diagram in Dart, demonstrating the Interface pattern where multiple classes implement a common interface.I’ve implemented the UML diagram demonstrating the Interface Pattern with these key design elements:
- Interface Definition:
FlyingTransport
is defined as an abstract class (Dart’s way of creating interfaces)- It declares the
fly()
method that all implementers must provide
- Multiple Implementations:
Helicopter
,Airplane
, andDomesticatedGryphon
all implement theFlyingTransport
interface- Each provides its own unique implementation of the
fly()
method
- Dependency Inversion Principle:
- The
Airport
class depends on theFlyingTransport
interface, not concrete implementations - The
accept()
method can work with any flying transport without knowing its specific type
- The
- Key Benefits Demonstrated:
- Polymorphism: Different flying vehicles can be treated uniformly through the interface
- Loose Coupling: Airport doesn’t need to know about specific vehicle types
- Extensibility: New flying transports can be added without modifying Airport
- Design Pattern Usage:
- This implements the Strategy Pattern where different flying behaviors are encapsulated
- Also demonstrates Dependency Injection as Airport accepts any FlyingTransport
The example shows how an airport can accept helicopters, airplanes, and even mythical creatures like gryphons, as long as they implement the FlyingTransport
interface. This makes the system flexible and extensible.