OOPs in Dart

Let’s dive into Object-Oriented Programming (OOP) in Dart! OOP is a way of writing code that organizes it around "objects" rather than just functions or logic. Think of objects as real-world things—like a car, a dog, or a book—that have properties (like color or size) and behaviors (like driving or barking). Dart, the language used for Flutter and more, supports OOP beautifully. I’ll break it down into simple topics and sub-topics with easy explanations and examples.
1. Basics of OOP
OOP revolves around four main ideas: Encapsulation, Inheritance, Polymorphism, and Abstraction. Dart uses these to help you write clean, reusable code. Let’s start with the building block: Classes and Objects.
1.1 Classes and Objects
Class: A blueprint for creating objects. It defines what an object can have (properties) and do (actions).
Object: An instance of a class—like a real thing made from the blueprint.
Example:
dart
class Dog {
String name = "Buddy"; // Property
int age = 3;
void bark() { // Behavior (method)
print("$name says Woof!");
}
}
void main() {
Dog myDog = Dog(); // Creating an object
print(myDog.name); // Output: Buddy
myDog.bark(); // Output: Buddy says Woof!
}
Here, Dog is the class, and myDog is the object. The object gets its own copy of name, age, and bark().
2. Encapsulation
Encapsulation means keeping an object’s data safe by hiding it and only allowing access through methods. It’s like locking your phone—only you can unlock it with the right key (method).
2.1 Private Variables
Use _ (underscore) before a variable or method name to make it private to the class.
Access it using getters and setters.
Example:
dart
class Person {
String _name = "Alice"; // Private variable
// Getter
String get name => _name;
// Setter
void set name(String newName) {
_name = newName;
}
}
void main() {
Person person = Person();
print(person.name); // Output: Alice
person.name = "Bob"; // Using setter
print(person.name); // Output: Bob
}
Here, _name is hidden, but we can still get or set it using name.
3. Inheritance
Inheritance lets one class "inherit" properties and methods from another class. It’s like a child inheriting traits from a parent.
3.1 Extending a Class
- Use the extends keyword to inherit.
Example:
dart
class Animal {
String type = "Unknown";
void eat() {
print("This $type is eating.");
}
}
class Cat extends Animal {
Cat() {
type = "Cat"; // Override the property
}
void meow() {
print("Meow!");
}
}
void main() {
Cat myCat = Cat();
myCat.eat(); // Output: This Cat is eating.
myCat.meow(); // Output: Meow!
}
Cat inherits type and eat() from Animal and adds its own meow().
3.2 Overriding Methods
- You can change an inherited method’s behavior using @override.
Example:
dart
class Animal {
void sound() {
print("Some sound");
}
}
class Dog extends Animal {
@override
void sound() {
print("Woof!");
}
}
void main() {
Dog myDog = Dog();
myDog.sound(); // Output: Woof!
}
The sound() method in Dog overrides the one in Animal.
4. Polymorphism
Polymorphism means "many forms." It lets you use a parent class type to refer to a child class object, and the correct method will still run.
Example:
dart
class Animal {
void sound() {
print("Generic sound");
}
}
class Dog extends Animal {
@override
void sound() {
print("Woof!");
}
}
class Cat extends Animal {
@override
void sound() {
print("Meow!");
}
}
void main() {
Animal myPet1 = Dog(); // Polymorphism
Animal myPet2 = Cat();
myPet1.sound(); // Output: Woof!
myPet2.sound(); // Output: Meow!
}
Even though myPet1 and myPet2 are of type Animal, they call the overridden methods from Dog and Cat.
5. Abstraction
Abstraction hides complex details and shows only what’s necessary. It’s like using a TV remote—you don’t need to know how it works inside, just the buttons.
5.1 Abstract Classes
- Use the abstract keyword. You can’t create objects from abstract classes, but they can be inherited.
Example:
dart
abstract class Shape {
void draw(); // Abstract method (no body)
}
class Circle extends Shape {
@override
void draw() {
print("Drawing a circle");
}
}
void main() {
Circle myShape = Circle();
myShape.draw(); // Output: Drawing a circle
}
Shape is abstract, so we implement draw() in Circle.
6. Constructors
Constructors are special methods that run when an object is created. They set up the object.
6.1 Default Constructor
- Automatically provided if you don’t define one.
Example:
dart
class Car {
String model;
Car(this.model); // Short constructor syntax
}
void main() {
Car myCar = Car("Toyota");
print(myCar.model); // Output: Toyota
}
6.2 Named Constructors
- Extra constructors with names for flexibility.
Example:
dart
class Car {
String model;
Car(this.model); // Default constructor
Car.named(String customModel) {
model = "Custom $customModel";
}
}
void main() {
Car car1 = Car("Honda");
Car car2 = Car.named("Ford");
print(car1.model); // Output: Honda
print(car2.model); // Output: Custom Ford
}
7. Interfaces and Mixins
Dart doesn’t have a separate interface keyword, but any class can act as an interface. Mixins add reusable code.
7.1 Implementing an Interface
- Use implements to follow a class’s structure.
Example:
dart
class Flyer {
void fly() {
print("Flying...");
}
}
class Bird implements Flyer {
@override
void fly() {
print("Bird is flying!");
}
}
void main() {
Bird bird = Bird();
bird.fly(); // Output: Bird is flying!
}
7.2 Mixins
- Use with to add extra behaviors.
Example:
dart
mixin Swimmer {
void swim() {
print("Swimming...");
}
}
class Duck extends Animal with Swimmer {
Duck() {
type = "Duck";
}
}
void main() {
Duck duck = Duck();
duck.eat(); // Output: This Duck is eating.
duck.swim(); // Output: Swimming...
}
Swimmer mixin adds swim() to Duck.
8. Static Members
Static variables and methods belong to the class itself, not objects.
Example:
dart
class Counter {
static int count = 0;
Counter() {
count++;
}
static void showCount() {
print("Total objects: $count");
}
}
void main() {
Counter c1 = Counter();
Counter c2 = Counter();
Counter.showCount(); // Output: Total objects: 2
}
count and showCount() are shared across all objects.
Summary
Here’s what we covered:
Classes and Objects: Blueprints and instances.
Encapsulation: Hiding data with private variables, getters, and setters.
Inheritance: Reusing code with extends and overriding.
Polymorphism: Using parent types for child objects.
Abstraction: Simplifying with abstract classes.
Constructors: Setting up objects.
Interfaces and Mixins: Adding structure and reusable behaviors.
Static Members: Class-level data and methods.
OOP in Dart is all about making code organized, reusable, and easy to understand. Practice these with small projects—like a pet simulator or a simple game—and you’ll get the hang of it! Let me know if you want more examples or help with anything specific.
Subscribe to my newsletter
Read articles from Singaraju Saiteja directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Singaraju Saiteja
Singaraju Saiteja
I am an aspiring mobile developer, with current skill being in flutter.