Menu
Coddy logo textTech

Implementing vs Extending

Part of the Object Oriented Programming section of Coddy's Dart journey — lesson 47 of 110.

Now that you understand both extends and implements, let's clarify when to use each one.

Use extends when you want to inherit behavior. Your subclass gets all the parent's code for free and can build upon it:

class Animal {
  void breathe() {
    print('Breathing...');
  }
}

class Dog extends Animal {
  void bark() {
    print('Woof!');
  }
}

void main() {
  var dog = Dog();
  dog.breathe();  // Inherited - works automatically
  dog.bark();
}

Use implements when you want to guarantee a structure without inheriting code. You must write every method yourself:

class Robot implements Animal {
  @override
  void breathe() {
    print('Ventilating circuits...');  // Completely custom implementation
  }
}

The key difference: extends says "I am a type of this" while implements says "I can do what this does." A Dog is an Animal and breathes the same way. A Robot isn't an animal, but it can fulfill the same contract with its own logic.

Remember: you can only extend one class, but you can implement many interfaces. Choose extends for true inheritance relationships, and implements when you need flexibility or want to enforce a contract without sharing implementation details.

challenge icon

Challenge

Easy

Let's build a worker system that demonstrates when to use extends versus implements. You'll create a base worker class and then show both approaches: one class that truly "is a" worker and inherits behavior, and another that simply "can do" what a worker does but with completely custom logic.

You'll organize your code into two files:

  • worker.dart: Define your worker hierarchy here:
    • A Worker class with a String name property and a constructor. Include a method work() that prints [name] is working... and a method takeBreak() that prints [name] takes a coffee break
    • An OfficeWorker class that extends Worker. Add a String department property. Override work() to print [name] is typing reports in [department] but keep the inherited takeBreak() behavior
    • A RobotWorker class that implements Worker. Add a String model property. Since robots aren't really workers but can do what workers do, provide completely custom implementations: work() should print Robot [model] is assembling parts and takeBreak() should print Robot [model] is recharging
  • main.dart: Import your worker file and demonstrate both approaches:
    • Create an OfficeWorker named 'Alice' in the 'Marketing' department
    • Create a RobotWorker with model 'RX-7'
    • For the office worker, call work() then takeBreak()
    • Print an empty line
    • For the robot worker, call work() then takeBreak()

Notice how OfficeWorker inherits takeBreak() automatically because it extends Worker - it truly "is a" worker. Meanwhile, RobotWorker must provide its own implementation for everything because it only implements the interface - it "can do" what a worker does, but in its own robotic way.

Expected output:

Alice is typing reports in Marketing
Alice takes a coffee break

Robot RX-7 is assembling parts
Robot RX-7 is recharging

Cheat sheet

Use extends to inherit behavior from a parent class. The subclass automatically gets all parent methods and can override them:

class Animal {
  void breathe() {
    print('Breathing...');
  }
}

class Dog extends Animal {
  void bark() {
    print('Woof!');
  }
}

void main() {
  var dog = Dog();
  dog.breathe();  // Inherited automatically
  dog.bark();
}

Use implements to guarantee a structure without inheriting code. You must provide your own implementation for every method:

class Robot implements Animal {
  @override
  void breathe() {
    print('Ventilating circuits...');
  }
}

Key differences:

  • extends: "I am a type of this" - true inheritance with shared code
  • implements: "I can do what this does" - enforces a contract with custom logic
  • You can only extend one class, but implement multiple interfaces

Choose extends for true parent-child relationships where behavior should be inherited. Choose implements when you need flexibility or want to enforce a contract without sharing implementation.

Try it yourself

import 'worker.dart';

void main() {
  // TODO: Create an OfficeWorker named 'Alice' in the 'Marketing' department
  
  // TODO: Create a RobotWorker with model 'RX-7'
  
  // TODO: For the office worker, call work() then takeBreak()
  
  // TODO: Print an empty line
  
  // TODO: For the robot worker, call work() then takeBreak()
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming