Menu
Coddy logo textTech

Implementare vs estendere

Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 47 di 110.

Ora che hai compreso sia extends sia implements, chiariamo quando usare ciascuno dei due.

Usa extends quando vuoi ereditare un comportamento. La tua sottoclasse ottiene gratuitamente tutto il codice della classe genitore e può basarsi su di esso:

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

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

void main() {
  var dog = Dog();
  dog.breathe();  // Ereditato - funziona automaticamente
  dog.bark();
}

Usa implements quando vuoi garantire una struttura senza ereditare codice. Devi scrivere ogni metodo tu stesso:

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

La differenza fondamentale: extends dice «Sono un tipo di questo», mentre implements dice «Posso fare ciò che fa questo». Un Dog è un Animal e respira allo stesso modo. Un Robot non è un animale, ma può rispettare lo stesso contratto con la propria logica.

Ricorda: puoi estendere una sola classe, ma puoi implementare molte interfacce. Scegli extends per le vere relazioni di ereditarietà e implements quando hai bisogno di flessibilità o vuoi imporre un contratto senza condividere i dettagli dell'implementazione.

challenge icon

Sfida

Facile

Costruiamo un sistema di lavoratori che mostri quando usare extends invece di implements. Creerai una classe base Worker e mostrerai poi entrambi gli approcci: una classe che davvero "is a" worker ed eredita il comportamento, e un'altra che semplicemente "can do" ciò che fa un lavoratore, ma con una logica completamente personalizzata.

Organizzerai il codice in due file:

  • worker.dart: definisci qui la gerarchia dei lavoratori:
    • Una classe Worker con una proprietà String name e un costruttore. Includi un metodo work() che stampa [name] is working... e un metodo takeBreak() che stampa [name] takes a coffee break
    • Una classe OfficeWorker che estende Worker. Aggiungi una proprietà String department. Sovrascrivi work() per stampare [name] is typing reports in [department], mantenendo però il comportamento ereditato di takeBreak()
    • Una classe RobotWorker che implementa Worker. Aggiungi una proprietà String model. Poiché i robot non sono davvero lavoratori, ma possono fare ciò che fanno i lavoratori, fornisci implementazioni completamente personalizzate: work() dovrebbe stampare Robot [model] is assembling parts e takeBreak() dovrebbe stampare Robot [model] is recharging
  • main.dart: importa il file dei lavoratori e mostra entrambi gli approcci:
    • Crea un OfficeWorker chiamato 'Alice' nel reparto 'Marketing'
    • Crea un RobotWorker con il modello 'RX-7'
    • Per il lavoratore dell'ufficio, chiama work() e poi takeBreak()
    • Stampa una riga vuota
    • Per il lavoratore robot, chiama work() e poi takeBreak()

Nota come OfficeWorker eredita automaticamente takeBreak() perché estende Worker: è davvero "is a" worker. Nel frattempo, RobotWorker deve fornire una propria implementazione per tutto perché implementa soltanto l'interfaccia: "can do" ciò che fa un lavoratore, ma a modo suo, da robot.

Output previsto:

Alice is typing reports in Marketing
Alice takes a coffee break

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

Provalo tu

import 'worker.dart';

void main() {
  // TODO: Crea un OfficeWorker di nome 'Alice' nel reparto 'Marketing'
  
  // TODO: Crea un RobotWorker con modello 'RX-7'
  
  // TODO: Per l'impiegato d'ufficio, chiama work() e poi takeBreak()
  
  // TODO: Stampa una riga vuota
  
  // TODO: Per il lavoratore robot, chiama work() e poi takeBreak()
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Dart online