Euristica su quando dovrebbe una sottoclasse e quando non [chiusa]

1

Ci sono dei buoni consigli quando si dovrebbe creare una sottoclasse e quando no?

È chiaro che dovremmo non sottoclasse quando

  • vogliamo riutilizzare un singolo metodo di qualche classe
  • sostituiamo tutti i metodi, cambiando completamente il comportamento della superclasse.

Ma nella vita reale, è più difficile decidere. Ad esempio, ho una classe BasicToolbar , che ha diversi pulsanti disposti su un pannello. Esiste una seconda classe ExtendedToolbar , che dovrebbe

  • hanno alcuni pulsanti aggiuntivi
  • cambia l'ordine di tutti i pulsanti
  • a condizione nascondi / rimuovi un paio di pulsanti dalla classe genitore

Tendo a sottoclasse per riutilizzare quei pulsanti e sovrascrivere la logica di ordinamento / aggiunta, ma la rimozione occasionale di un pulsante della classe genitore sembra essere contraria all'idea di ereditarietà.

Qualsiasi opinione è gradita.

    
posta damluar 22.01.2015 - 21:33
fonte

3 risposte

3

Il Principio di Substiution di Liskov è di gran lunga la migliore "euristica" che conosca per determinare se una sottoclasse diretta è una buona idea.

Supponiamo che tu abbia una classe base Foo e le classi derivate da Bar1 a Bar9. In poche parole, l'LSP afferma che qualsiasi blocco di codice che utilizza Foo deve funzionare correttamente, indipendentemente da quale dei nove tipi di Bar in realtà Foo .

Dal punto di vista dell'utente, ciò significa che il codice che utilizza la classe base dovrebbe essere in grado di funzionare quasi esclusivamente con quella classe base, senza preoccuparsi di quale sia il tipo effettivo dell'oggetto.

Dal punto di vista del realizzatore, ciò significa che ciascuna sottoclasse deve implementare l'intera interfaccia della classe base, incluse tutte le proprietà semantiche implicite, senza sorprese o restrizioni aggiuntive.

Se la sottoclasse che stai pensando di scrivere non seguirà queste regole, è un'indicazione molto strong che non dovresti usare l'ereditarietà.

Per quanto riguarda l'esempio della barra degli strumenti, non penso che abbia molto senso utilizzare l'ereditarietà in questo modo. Preferisco avere le classi Button, una generica barra degli strumenti che può contenere qualsiasi disposizione di pulsanti, quindi rendere BasicToolbar e ExtendedToolbar essere oggetti con un membro della barra degli strumenti a cui aggiungono i pulsanti nei loro costruttori. Se condividono un gruppo di pulsanti, rendere le classi BackButton / LikeButton / UpvoteButton con un membro Button e lasciare che le barre degli strumenti li contengano. L'utilizzo dell'eredità in qualsiasi punto di questa disposizione non farà che aumentare le restrizioni inutilmente rigide su come riordinare queste classi in futuro.

    
risposta data 23.01.2015 - 02:15
fonte
1

Dipende dalle convenzioni e dalle linee guida per un linguaggio di programmazione specifico. In C # non è facile delegare metodi a un oggetto interno (richiede codice esplicito). Quindi l'ereditarietà può essere più facile. Quando si crea un'API pubblica basata su rete, è spesso consigliabile l'ereditarietà, per semplificare la scoperta per l'utente dell'API.

    
risposta data 23.01.2015 - 00:57
fonte
0

Un uso comune è quando si desidera utilizzare il modello di metodo del modello .

Io quel pattern scrivi lo scheletro di un algoritmo in una classe abstrac. In alcune parti di quello scheletro puoi usare certi metodi che non sono implementati.

Sottoclasse implementa quei metodi che completano l'algoritmo. Ciò può anche essere ottenuto senza ereditarietà mediante l'iniezione e / o delegati.

In generale non dovresti sottoclasse dove non c'è una "relazione" tra classe.

Un altro patter che usa l'ereditarietà è il patter decoratore che è simile all'esempio di barra degli strumenti che hai fornito.

    
risposta data 23.01.2015 - 01:42
fonte

Leggi altre domande sui tag