Quali sono gli svantaggi durante la progettazione di una classe?

3

Quando ho letto il libro Effective Java capitolo 4, ho incontrato alcune frasi ma non riesco a pensarle:

  1. Qual è l'implementazione quando si progetta una classe, perché la sottoclasse si baserà sui dettagli di implementazione della superclasse?
  2. Perché l'eredità interrompe l'incapsulamento?
posta ohyeahchenzai 26.05.2012 - 15:52
fonte

3 risposte

3

Domanda di implementazione

Questo è un modo sfumato per osservare la classe base e le classi derivate. L'implicazione è che si dovrebbe considerare ciò che la classe derivata (anche in sottoclasse) eredita come una specie di contratto con la classe base. Ciò che la classe base fornisce, o non fornisce, influenza il modo in cui le classi derivate possono essere utilizzate e quanto lavoro ci vuole.

Quindi usiamo una classe base di "Shape" con la proprietà "Name."
Ho ricavato un "Quadrato" e un "Cerchio" da Forma, e sono in grado di utilizzare il loro campo Nome ereditato per impostare il nome dell'oggetto.

Finora, tutto bene.

Ora aggiungiamo una proprietà "Area" e un metodo "GetArea ()" a Shape.
Possiamo codificare GetArea () all'interno di Shape perché restituiamo semplicemente la proprietà Area.
Ma come facciamo a fare in modo che le forme calcolino la loro area? Non possiamo scrivere Shape.CalcArea () poiché non abbiamo dato alcuna conoscenza delle dimensioni della forma. Quindi siamo obbligati a scrivere una routine CalcArea () in ciascuna delle classi derivate in modo che Shape.GetArea () non abbia esito negativo. (fallimento == non produce risultati attesi)

Ci sono modi per risolvere questo attraverso override, virtuals, abstract, ecc ... basati sul linguaggio. Ma il punto della frase è farti riflettere attraverso quelle relazioni.

Dobbiamo riflettere perché ora vogliamo usare Shape per ottenere una classe "Cone". I coni non hanno un'area, hanno un volume. E ora ti occupi delle domande sulla progettazione di classe di ciò che dovrebbe essere implementato dalla classe base, e cosa dovrebbero implementare le classi derivate.

Incapsulamento

Per definizione, la classe derivata può vedere e accedere a tutto ciò che la classe base ha da offrire. Nell'esempio Shape, questa è una "cosa buona" e vogliamo condividere esplicitamente tutto, dalla base alla classe derivata.

Ma diciamo che in Shape v2.0, ho bisogno di pre-compilare cose da un database. Così faccio derivare Shape da una classe di connessione al database "DBConn". Ora, tutti i miei cerchi, quadrati e coni sono anche connessioni al database. Ogni singola forma ha accesso a tutte le informazioni di connessione al database ed è potenzialmente strettamente legata al modo in cui funziona effettivamente DBConn.
Quindi, invece di chiamare Square.myDBConn.Connect (), posso semplicemente chiamare Square.Connect (). Quindi, se dovessi voler modificare l'implementazione di Connect () in un secondo momento, dovrò esaminare tutte le classi di forma derivate per vedere cosa potrebbe rompere con quel cambiamento.

Al suo punto cruciale, questa è la domanda di incapsulamento "Is A ..." vs. "Has A ..." che deve essere sempre considerata quando si combinano gli oggetti.

    
risposta data 27.05.2012 - 14:07
fonte
1

Una sottoclasse si basa sull'implementazione della sua super classe perché eredita da essa. Qualsiasi cosa dalla super classe visibile dalla sottoclasse diventa una dipendenza e una potenziale fonte di errore. Se l'implementazione della super classe cambia, allora la sottoclasse potrebbe non essere più corretta, o addirittura compilare. Ciò non significa che l'ereditarietà sia una cosa cattiva , significa solo che devi stare attento quando progetti le tue classi. È utile documentare in modo esplicito le tue intenzioni.

    
risposta data 26.05.2012 - 17:35
fonte
1

Questo è davvero un commento al tuo commento, ma era troppo difficile scrivere come commento.

When a subclass inherit a super class , why does it depend on its super class's implementation details.This is what am I considered .I can't grasp the meaning of your first two sentence from your comment ,can you explain it in a more concrete way, or give me a link to another page with examples to describe it. –

Diciamo che hai una classe che rappresenta un mazzo di carte, e ha un metodo deal () che restituisce la prima carta del mazzo, e un metodo shuffle () che mescola le carte nel mazzo.

Lo sottoponi a sottolocazione e sostituisci la riproduzione casuale, ad esempio, per renderlo più casuale della classe originale.

Ora, ad un certo punto nel futuro, qualcuno modifica la classe base e cambia deal (). Originariamente, prendeva la carta e la distribuiva, e spostava la carta sul fondo del mazzo, in modo che alla fine, se continuavi a trattare, avresti recuperato la carta e l'ordine sarebbe ripetuto.

Ma ora il metodo è cambiato in modo che l'affare controlli se la carta è già stata restituita e, in caso affermativo, si rimescolerà automaticamente, una volta che tutte le carte sono state distribuite una sola volta.

Il tuo sottoclasse, non saprà di questo cambiamento di implementazione e potrebbe esibire uno strano comportamento. Diciamo che il metodo shuffle nella tua classe derivata è molto lento, 3-4 secondi. Ora, all'improvviso, quando si tratta, c'è un ritardo dovuto allo shuffle. La classe base non mostra alcun problema, perché il suo shuffle è molto veloce.

Questo è ciò che intendono in base ai dettagli di implementazione della sua super classe.

    
risposta data 08.06.2012 - 17:44
fonte

Leggi altre domande sui tag