Ereditarietà, composizione e protocolli

6

Sto leggendo un libro su concetti generali orientati agli oggetti per cercare di acquisire una solida comprensione di tutto. Una cosa che mi sta buttando fuori è la differenza tra ereditarietà e composizione. So che in termini di ereditarietà, è "is-a" con la sottoclasse. Come una classe Employee eredita dalla classe Person, perché un dipendente è "una persona". La sottoclasse di Composition è "ha-a". Ad esempio, una classe Car eredita dalla classe del Volante perché l'auto "ha-un" volante.

Fantastico, finora. Ma ... questa non è ancora eredità? Comprendo la differenza tra "is-a" e "has-a". Capisco anche che Composition sta fondamentalmente combinando più classi per creare un'altra classe che contiene tutti quegli oggetti. Ho due domande:

  1. La composizione non è ancora una forma di ereditarietà in qualche modo?
  2. Scrivendo questo, forse ho risposto alla mia stessa domanda. In Objective-C, utilizziamo i protocolli per specificare ciò che deve essere ereditato e ciò che è facoltativo. Sta semplicemente lanciando un protocollo nell'intestazione che cosa distingue l'ereditarietà e la sottoclasse? Usiamo i protocolli sia nell'ereditarietà che nella composizione?

Comprendo abbastanza bene la differenza, e so come utilizzare ciascuno attraverso i miei programmi. Immagino che sia solo una questione di semantica, se la composizione è davvero una forma di ereditarietà o meno.

    
posta Henry F 17.11.2014 - 20:02
fonte

1 risposta

7

No, i due concetti sono diversi.

Una migliore analogia con l'auto sarebbe per quanto riguarda il motore. Supponiamo di avere un'interfaccia per un motore. Potrebbe avere proprietà come numero di cilindri e RPM. Potresti essere in grado di invocare comportamenti come l'apertura e la chiusura dell'acceleratore. Tuttavia, questa è solo un'interfaccia: il motore non è un'implementazione. La classe Car ha: un motore: quando costruisci un'auto, installi qualcosa che implementa l'interfaccia di quel motore. Molte macchine hanno motori diversi come opzioni.

Ora c'è l'implementazione. Forse definiamo una classe SixCylinderEngine . È un motore perché implementa quell'interfaccia. Può essere utilizzato ovunque sia utilizzata l'interfaccia del motore.

Ma aspetta! Alcune persone vogliono una versione sovralimentata del motore. Questo non è semplice come cambiare una variabile nel motore esistente, questo è un grande cambiamento. Parti diverse, una seconda cinghia di trasmissione, un altro componente principale (il compressore), più potenza, ecc.

Un modo per ottenere questo risultato è la sottoclasse di SixCylinderEngine e aggiungere il compressore. Ciò ha valore, ma può introdurre complesse interdipendenze tra sottoclasse e superclasse. Quello sarebbe un altro è-una relazione.

Al contrario, definiamo una classe SuperchargedSixCylinderEngine che implementa direttamente Engine (is-a). Per riutilizzare il codice, contiene un SixCylinderEngine internamente e delegati alcune funzioni (has-a).

Da qui, il passo successivo è avere un SuperchargedEngine che accetti qualsiasi motore: 6, 8, 10 cilindri, tutto quello che vuoi.

Ecco un esempio di codice della differenza.

ereditarietà:

public int getHorsepower() {
  return 1.4 * super.getHorsepower();
}

Composizione:

private Engine engine;

public SuperchargedEngine(Engine e) {
  engine = e;
}

public int getHorsepower() {
  return 1.4 * engine.getHorsepower();
}
    
risposta data 17.11.2014 - 20:29
fonte