🚀 Limited spots available for Summer '25 cohort — Apply now before it's too late!
Day 5: Object-Oriented Programming in Dart

Welcome to Day 5 of the "Hundred Days of Flutter" course! Today, we'll explore Object-Oriented Programming (OOP) concepts in Dart, which are essential for building well-structured and maintainable Flutter applications.

Classes and Objects

Classes are the building blocks of OOP in Dart. They define the structure and behavior of objects.

Basic Class Definition

class Person {
  // Properties (instance variables)
  String name;
  int age;
 
  // Constructor
  Person(this.name, this.age);
 
  // Methods
  void sayHello() {
    print('Hello, my name is $name');
  }
 
  // Getter
  String get info => '$name is $age years old';
 
  // Setter
  set setAge(int value) {
    if (value >= 0) {
      age = value;
    }
  }
}
 
void main() {
  // Creating an object
  final person = Person('John', 25);
  person.sayHello(); // Output: Hello, my name is John
  print(person.info); // Output: John is 25 years old
  person.setAge = 26;
}

Private Members

Dart uses the underscore (_) prefix to make members private:

class BankAccount {
  String _accountNumber; // Private property
  double _balance; // Private property
 
  BankAccount(this._accountNumber, this._balance);
 
  // Public getter
  double get balance => _balance;
 
  // Public method
  void deposit(double amount) {
    if (amount > 0) {
      _balance += amount;
    }
  }
}

Constructors

Dart provides several types of constructors:

Default Constructor

class Car {
  String brand;
  String model;
 
  // Default constructor
  Car(this.brand, this.model);
 
  // Named constructor
  Car.toyota(this.model) : brand = 'Toyota';
 
  // Factory constructor
  factory Car.fromJson(Map<String, dynamic> json) {
    return Car(json['brand'], json['model']);
  }
}

Constructor Initialization List

class Point {
  final double x;
  final double y;
 
  Point(double x, double y)
      : x = x,
        y = y,
        assert(x >= 0),
        assert(y >= 0);
}

Inheritance

Dart supports single inheritance and interfaces.

Basic Inheritance

class Animal {
  String name;
 
  Animal(this.name);
 
  void makeSound() {
    print('Some sound');
  }
}
 
class Dog extends Animal {
  String breed;
 
  Dog(String name, this.breed) : super(name);
 
  @override
  void makeSound() {
    print('Woof!');
  }
 
  void fetch() {
    print('$name is fetching the ball');
  }
}
 
void main() {
  final dog = Dog('Rex', 'German Shepherd');
  dog.makeSound(); // Output: Woof!
  dog.fetch(); // Output: Rex is fetching the ball
}

Abstract Classes

abstract class Shape {
  double get area;
  double get perimeter;
}
 
class Circle extends Shape {
  final double radius;
 
  Circle(this.radius);
 
  @override
  double get area => 3.14 * radius * radius;
 
  @override
  double get perimeter => 2 * 3.14 * radius;
}
 
class Rectangle extends Shape {
  final double width;
  final double height;
 
  Rectangle(this.width, this.height);
 
  @override
  double get area => width * height;
 
  @override
  double get perimeter => 2 * (width + height);
}

Interfaces

Dart doesn't have a dedicated interface keyword. Instead, any class can be used as an interface.

class Flyable {
  void fly() {
    print('Flying');
  }
}
 
class Bird implements Flyable {
  @override
  void fly() {
    print('Bird is flying');
  }
}
 
class Airplane implements Flyable {
  @override
  void fly() {
    print('Airplane is flying');
  }
}

Mixins

Mixins are a way to reuse code in multiple class hierarchies:

mixin Swimming {
  void swim() {
    print('Swimming');
  }
}
 
mixin Flying {
  void fly() {
    print('Flying');
  }
}
 
class Duck extends Animal with Swimming, Flying {
  Duck(String name) : super(name);
 
  @override
  void makeSound() {
    print('Quack!');
  }
}
 
void main() {
  final duck = Duck('Donald');
  duck.swim(); // Output: Swimming
  duck.fly(); // Output: Flying
  duck.makeSound(); // Output: Quack!
}

Static Members

Static members belong to the class itself, not to instances:

class MathUtils {
  static const double pi = 3.14159;
 
  static double square(double number) {
    return number * number;
  }
 
  static double sum(List<double> numbers) {
    return numbers.reduce((a, b) => a + b);
  }
}
 
void main() {
  print(MathUtils.pi); // Output: 3.14159
  print(MathUtils.square(5)); // Output: 25
  print(MathUtils.sum([1, 2, 3, 4, 5])); // Output: 15
}

Knowledge Check

Let's test your understanding of today's concepts:

?

It's time to take a quiz!

What is the purpose of the 'extends' keyword in Dart?

?

It's time to take a quiz!

Which of the following is true about abstract classes in Dart?

?

It's time to take a quiz!

What is the purpose of mixins in Dart?

Mini-Challenge: Shape Calculator

Create a shape calculator that demonstrates your understanding of OOP concepts:

  1. Create an abstract Shape class with abstract methods for area and perimeter
  2. Create concrete classes for different shapes (Circle, Rectangle, Triangle)
  3. Create a ShapeCalculator class that can:
    • Calculate the total area of multiple shapes
    • Find the shape with the largest area
    • Print information about all shapes

Here's a starting point:

abstract class Shape {
  double get area;
  double get perimeter;
  String get name;
}
 
class Circle extends Shape {
  final double radius;
 
  Circle(this.radius);
 
  @override
  double get area => 3.14 * radius * radius;
 
  @override
  double get perimeter => 2 * 3.14 * radius;
 
  @override
  String get name => 'Circle';
}
 
class ShapeCalculator {
  final List<Shape> shapes = [];
 
  void addShape(Shape shape) {
    shapes.add(shape);
  }
 
  double get totalArea {
    return shapes.fold(0, (sum, shape) => sum + shape.area);
  }
 
  Shape get largestShape {
    return shapes.reduce((a, b) => a.area > b.area ? a : b);
  }
 
  void printShapes() {
    shapes.forEach((shape) {
      print('${shape.name}:');
      print('  Area: ${shape.area}');
      print('  Perimeter: ${shape.perimeter}');
      print('');
    });
  }
}

Key Takeaways

  • Classes are the building blocks of OOP in Dart
  • Constructors can be default, named, or factory
  • Inheritance is supported through the extends keyword
  • Abstract classes can have both abstract and concrete methods
  • Interfaces are implemented using the implements keyword
  • Mixins allow code reuse across multiple class hierarchies
  • Static members belong to the class itself, not instances

Tomorrow, we'll start exploring Flutter's widget system and begin building our first Flutter application!

Previous

Day 4: Collections & Null Safety in Dart

Master Dart's collection types and null safety features to write more robust and type-safe code in your Flutter applications.

Start Previous Day
Next Up

Day 6: Flutter Widget Tree & Stateless Widgets

Learn about Flutter's widget tree structure and how to create stateless widgets to build the foundation of your Flutter applications.

Start Next Day