Menu
Coddy logo textTech

Fondamenti di polimorfismo

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

Il polimorfismo significa «molte forme»: è la capacità di trattare oggetti di classi diverse tramite un'interfaccia comune. Quando hai un riferimento a una classe genitore, può puntare a un oggetto di qualsiasi classe figlia e viene chiamato il metodo corretto in base al tipo effettivo dell'oggetto.

Questo è potente perché puoi scrivere codice che funziona con il tipo genitore, ma gestisce automaticamente correttamente tutti i tipi figli:

class Animal {
  void speak() => print('Some sound');
}

class Dog extends Animal {
  @override
  void speak() => print('Woof!');
}

class Cat extends Animal {
  @override
  void speak() => print('Meow!');
}

void main() {
  Animal myPet = Dog();  // Tipo genitore, oggetto figlio
  myPet.speak();  // Output: Woof!
  
  myPet = Cat();  // Stessa variabile, oggetto diverso
  myPet.speak();  // Output: Meow!
}

La variabile myPet è dichiarata come Animal, ma contiene un Dog o un Cat. Quando viene chiamato speak(), Dart verifica il tipo effettivo dell'oggetto in fase di esecuzione e chiama il metodo sovrascritto appropriato.

Questo ti permette di scrivere funzioni flessibili che funzionano con qualsiasi sottoclasse:

void makeAllSpeak(List<Animal> animals) {
  for (var animal in animals) {
    animal.speak();  // Ogni animale si esprime a modo suo
  }
}

void main() {
  var pets = [Dog(), Cat(), Dog()];
  makeAllSpeak(pets);
  // Output: Woof! Meow! Woof!
}

La funzione non deve conoscere Dog o Cat: funziona semplicemente con Animal. Questo rende il tuo codice più estensibile, poiché aggiungere nuovi tipi di animali non richiede modifiche alle funzioni esistenti.

challenge icon

Sfida

Facile

Costruiamo un sistema di strumenti musicali che mostri il polimorfismo in azione. Creerai una classe base Instrument e diversi tipi di strumenti, poi scriverai una funzione che può far suonare insieme qualsiasi gruppo di strumenti, senza conoscerne i tipi specifici.

Organizzerai il codice in due file:

  • instruments.dart: definisci qui la gerarchia degli strumenti:
    • Una classe Instrument con una proprietà String name e un costruttore. Includi un metodo play() che stampa [name] makes a sound
    • Una classe Guitar che estende Instrument e sovrascrive play() per stampare [name] strums melodically
    • Una classe Drum che estende Instrument e sovrascrive play() per stampare [name] beats rhythmically
    • Una classe Piano che estende Instrument e sovrascrive play() per stampare [name] plays harmoniously
    Crea anche una funzione performConcert(List<Instrument> instruments) che stampa Concert begins!, poi scorre l'elenco chiamando play() su ogni strumento e infine stampa Concert ends!
  • main.dart: importa il file degli strumenti e mostra il polimorfismo creando una band composta da strumenti diversi:
    • Crea un elenco di tipo List<Instrument> contenente una Guitar chiamata 'Acoustic', un Drum chiamato 'Snare' e un Piano chiamato 'Grand'
    • Passa questo elenco a performConcert()

Nota come performConcert() utilizzi il tipo genitore Instrument, eppure ogni strumento suoni a modo suo. Questo è il polimorfismo: la stessa chiamata di metodo produce comportamenti diversi in base al tipo effettivo dell'oggetto.

Output previsto:

Concert begins!
Acoustic strums melodically
Snare beats rhythmically
Grand plays harmoniously
Concert ends!

Provalo tu

import 'instruments.dart';

void main() {
  // TODO: Crea una List<Instrument> che contenga:
  // - Una Guitar chiamata 'Acoustic'
  // - Un Drum chiamato 'Snare'
  // - Un Piano chiamato 'Grand'
  
  
  // TODO: Chiama performConcert() con la tua lista di strumenti
  
}
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