Menu
Coddy logo textTech

Implementar vs. Extender

Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy — lección 47 de 110.

Ahora que entiendes tanto extends como implements, aclaremos cuándo usar cada uno.

Utiliza extends cuando quieras heredar comportamiento. Tu subclase obtiene todo el código del padre de forma gratuita y puede construir sobre él:

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

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

void main() {
  var dog = Dog();
  dog.breathe();  // Heredado - funciona automáticamente
  dog.bark();
}

Utiliza implements cuando quieras garantizar una estructura sin heredar código. Debes escribir cada método tú mismo:

class Robot implements Animal {
  @override
  void breathe() {
    print('Ventilating circuits...');  // Implementación completamente personalizada
  }
}

La diferencia clave: extends dice "soy un tipo de esto" mientras que implements dice "puedo hacer lo que esto hace". Un Dog es un Animal y respira de la misma manera. Un Robot no es un animal, pero puede cumplir el mismo contrato con su propia lógica.

Recuerda: solo puedes extender una clase, pero puedes implementar muchas interfaces. Elige extends para relaciones de herencia verdaderas, y implements cuando necesites flexibilidad o quieras imponer un contrato sin compartir detalles de implementación.

challenge icon

Desafío

Fácil

Vamos a construir un sistema de trabajadores que demuestre cuándo usar extends frente a implements. Crearás una clase base de trabajador y luego mostrarás ambos enfoques: una clase que realmente "es un" trabajador y hereda el comportamiento, y otra que simplemente "puede hacer" lo que hace un trabajador pero con una lógica completamente personalizada.

Organizarás tu código en dos archivos:

  • worker.dart: Define tu jerarquía de trabajadores aquí:
    • Una clase Worker con una propiedad String name y un constructor. Incluye un método work() que imprima '$name is working...' y un método takeBreak() que imprima '$name takes a coffee break'
    • Una clase OfficeWorker que extienda (extends) Worker. Añade una propiedad String department. Sobrescribe work() para que imprima '$name is typing reports in $department' pero mantén el comportamiento heredado de takeBreak()
    • Una clase RobotWorker que implemente (implements) Worker. Añade una propiedad String model. Dado que los robots no son realmente trabajadores pero pueden hacer lo que hacen los trabajadores, proporciona implementaciones completamente personalizadas: work() debe imprimir 'Robot $model is assembling parts' y takeBreak() debe imprimir 'Robot $model is recharging'
  • main.dart: Importa tu archivo de trabajadores y demuestra ambos enfoques:
    • Crea un OfficeWorker llamado 'Alice' en el departamento 'Marketing'
    • Crea un RobotWorker con el modelo 'RX-7'
    • Para el trabajador de oficina, llama a work() y luego a takeBreak()
    • Imprime una línea vacía
    • Para el robot trabajador, llama a work() y luego a takeBreak()

Observa cómo OfficeWorker hereda takeBreak() automáticamente porque extiende Worker; realmente "es un" trabajador. Mientras tanto, RobotWorker debe proporcionar su propia implementación para todo porque solo implementa la interfaz; "puede hacer" lo que hace un trabajador, pero a su propia manera robótica.

Salida esperada:

Alice is typing reports in Marketing
Alice takes a coffee break

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

Hoja de referencia

Usa extends para heredar el comportamiento de una clase padre. La subclase obtiene automáticamente todos los métodos del padre y puede sobrescribirlos:

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

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

void main() {
  var dog = Dog();
  dog.breathe();  // Heredado automáticamente
  dog.bark();
}

Usa implements para garantizar una estructura sin heredar código. Debes proporcionar tu propia implementación para cada método:

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

Diferencias clave:

  • extends: "Soy un tipo de esto" - herencia verdadera con código compartido
  • implements: "Puedo hacer lo que esto hace" - impone un contrato con lógica personalizada
  • Solo puedes extender una clase, pero puedes implementar múltiples interfaces

Elige extends para relaciones verdaderas de padre e hijo donde el comportamiento deba ser heredado. Elige implements cuando necesites flexibilidad o quieras imponer un contrato sin compartir la implementación.

Pruébalo tú mismo

import 'worker.dart';

void main() {
  // TODO: Crear un OfficeWorker llamado 'Alice' en el departamento de 'Marketing'
  
  // TODO: Crear un RobotWorker con el modelo 'RX-7'
  
  // TODO: Para el trabajador de oficina, llamar a work() y luego a takeBreak()
  
  // TODO: Imprimir una línea vacía
  
  // TODO: Para el trabajador robot, llamar a work() y luego a takeBreak()
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos