In che modo la progettazione per ereditarietà può comportare costi aggiuntivi? [chiuso]


12

Quindi volevo ereditare da a sealed classin csharp e mi sono bruciato. Non c'è modo di annullarlo se non si ha accesso alla fonte.

Poi mi ha fatto pensare "perché sealedesiste?". 4 mesi fa. Non sono riuscito a capirlo, nonostante abbia letto molte cose a riguardo, come:

Ho provato a digerire tutto da allora, ma è troppo per me. Alla fine, ieri ho provato di nuovo. Ho scansionato di nuovo tutti loro, oltre a pochi altri:

Alla fine, dopo molte riflessioni, ho deciso di modificare pesantemente la domanda originale in base al nuovo titolo.

La vecchia domanda era troppo ampia e soggettiva. Fondamentalmente stava chiedendo:

  1. Nel vecchio titolo: una buona ragione per usare sigillato
  2. Nel corpo: come modificare correttamente una classe sigillata? Dimentica l'eredità? Usa la composizione?

Ma ora, comprendendo (cosa che non ho fatto ieri) che tutto sealedciò che fa è prevenire l'eredità , e possiamo e dovremmo davvero usare la composizione sull'eredità , ho capito che ciò di cui avevo bisogno erano esempi pratici .

Immagino che la mia domanda qui sia (e in effetti lo sia sempre stata) esattamente cosa mi ha suggerito Mr.Mindor in una chat : in che modo la progettazione per l'eredità può causare costi aggiuntivi?


5
La domanda è formulata in modo piuttosto aggressivo e suona come un rant. Dovresti riformularlo se vuoi risposte pertinenti e obiettive.
Euforico

11
Vedi perché vengono sigillate così tante classi quadro? di Eric Lippert. Fornisce diversi buoni motivi per sigillare le lezioni.
Robert Harvey,

9
Quindi non hai letto l'articolo. Torna indietro e leggilo di nuovo. Si riduce a questo: non è possibile prevedere gli innumerevoli modi in cui un client potrebbe interrompere la tua classe estendendola. Puoi incolpare i tuoi clienti per questo, ma sei tu quello che dovrà supportarli.
Robert Harvey,

4
@Cawas Potrebbe, o potresti leggere l'articolo che ha collegato che lo spiega in dettaglio. Stava semplicemente riassumendo quell'articolo con il suo commento.
Servito il

7
Mi dispiace, ma non sono io quello che sta rantolando qui. La risposta alla tua domanda è molto semplice: sigilla una classe quando non vuoi sostenere l'eredità. Questo è tutto.
Robert Harvey,

Risposte:


27

Non è così difficile da capire. sealedè stato creato SPECIFICAMENTE per Microsoft al fine di semplificarne la vita, risparmiare tonnellate di denaro e aiutarne la reputazione. Dal momento che è una caratteristica del linguaggio anche tutti gli altri possono usarlo, ma probabilmente non avrai mai bisogno di usare sigillato.

La maggior parte delle persone si lamenta di non essere in grado di estendere un corso e, se lo fanno, dicono bene che tutti sanno che è responsabilità degli sviluppatori far funzionare correttamente. È corretto, TRANNE che le stesse persone non hanno idea della storia di Windows e uno dei problemi sealedsta cercando di risolvere.

Supponiamo che uno sviluppatore abbia esteso una classe core .Net (perché non esisteva il sigillo) e lo facesse funzionare perfettamente. Sì, per lo sviluppatore. Lo sviluppatore consegna il prodotto al cliente. L'app per sviluppatori funziona alla grande. Il cliente è contento. La vita è bella.

Ora Microsoft rilascia un nuovo sistema operativo, che include la correzione di bug in questa particolare classe core .Net. Il cliente desidera tenere il passo con i tempi e sceglie di installare il nuovo sistema operativo. All'improvviso, l'applicazione che piace tanto al cliente non funziona più, perché non ha tenuto conto dei bug corretti nella classe principale .Net.

Di chi è la colpa?

Coloro che hanno familiarità con la storia di Microsoft sanno che il nuovo sistema operativo Microsoft avrà la colpa e non il software applicativo che ha abusato delle librerie di Windows. Quindi diventa compito di Microsoft risolvere il problema anziché la società applicativa che ha creato il problema. Questo è uno dei motivi per cui il codice di Windows è diventato gonfio. Da quello che ho letto, il codice del sistema operativo Windows è disseminato di specifici if-then verifica se un'applicazione e una versione specifiche sono in esecuzione e, in tal caso, eseguono un'elaborazione speciale per consentire al programma di funzionare. Sono un sacco di soldi spesi da Microsoft per correggere l'incompetenza di un'altra società.

L'uso sealednon elimina completamente lo scenario sopra riportato, ma aiuta.


4
@Cawas È abbastanza difficile abusarne. Eric Lippert ha affermato in diverse occasioni che le classi, come i metodi, erano tutte sealedpredefinite, a meno che non fossero state specificamente sigillate, semplicemente perché così poche classi sono effettivamente progettate per essere ereditate. È molto più probabile che la tua classe non sia stata costruita per supportarla, e dovresti assicurarti di aver speso quel tempo di sviluppo se stai facendo di tutto per contrassegnarlo come non sigillato.
Servito il

1
Penso che se le persone usano sigillati per il loro software di sviluppo interno, probabilmente lo stanno abusando o stanno semplicemente sprecando il tempo dell'azienda cercando di essere troppo perfetto. Dico probabilmente perché ci sono sempre casi in cui uno può avere un senso in uno scenario particolare. Tuttavia, per coloro che sviluppano software di tipo libreria, sospetto che sia molto utile per gli stessi motivi per cui Microsoft ha deciso che ce n'era bisogno.
Dunk

2
@Cawas La stragrande maggioranza delle classi scritte dalla maggior parte degli sviluppatori non avrà mai bisogno di essere ereditaria, e non sono scritti per l'eredità di supporto. Questo può essere trasmesso in modo rapido ed efficace ai lettori / utenti del codice creando il tipo sealed. Se fosse effettivamente l'opzione predefinita, significherebbe che se qualcuno ereditasse da un tipo, saprebbe che è stato creato per supportarlo.
Servito il

2
Svelare una classe non significherebbe che la classe è stata costruita per supportarla. Significa solo che qualcuno voleva ereditare dalla classe e annullarla. Nel migliore dei casi, l'uso di sigillato farà semplicemente riscrivere agli sviluppatori la funzionalità esistente (equivalente alla classe sigillata) ma il più delle volte, se il codice sorgente è disponibile, lo sveleranno semplicemente senza tener conto delle conseguenze. Avere il sigillo essere impostato in modo specifico e raramente, è meglio perché quindi lo sviluppatore potrebbe voler capire perché questa classe è sigillata. Troppe classi sigillate e a loro non importa perché.
Dunk,

1
Anche la sicurezza è un motivo per usarla! Prendi in considerazione un'applicazione sandbox che tenta di accedere a un file. La sandbox potrebbe testare le stringhe del nome file, ma cosa succede se un utente malintenzionato potrebbe inviarti un oggetto mutabile String e poi lo muteranno dopo il controllo di sicurezza ma prima dell'I / O? Credo che questo tipo di scenario sia il motivo per cui Java Stringè contrassegnato final(simile a sealed) e scommetto che la stessa logica è alla base di alcune decisioni C #.
Darien,

23

sealedè usato per indicare che lo scrittore della classe non l'ha progettato per essere ereditato. Niente di meno, niente di più.

Progettare correttamente un'interfaccia è già abbastanza difficile per molti programmatori. Progettare correttamente una classe che può essere potenzialmente ereditata aggiunge difficoltà e righe di codice. Più righe di codice scritte significano più codice da mantenere. Per evitare questa crescente difficoltà, sealedpuò dimostrare che la classe non è mai stata destinata a essere ereditata e, in questo contesto, sigillare una classe è una soluzione perfettamente valida a un problema .

Immagina il caso da cui CustomBoeing787deriva la classe Airliner. Questo CustomBoeing787sostituisce alcuni metodi protetti da Airliner, ma non tutti. Se lo sviluppatore ha abbastanza tempo e ne vale la pena, può testare l'unità della classe per assicurarsi che tutto funzioni come previsto, anche in un contesto in cui vengono chiamati metodi non scavalcati (ad esempio setter protetti che cambiano lo stato dell'oggetto). Se lo stesso sviluppatore (1) non ha tempo, (2) non vuole spendere ulteriori centinaia o migliaia di dollari del suo capo / cliente, o (3) non vuole scrivere codice aggiuntivo, non lo fa bisogno adesso (YAGNI), quindi può:

  • rilasciare il codice allo stato selvatico così com'è, considerando che è la preoccupazione dei programmatori che manterranno questo progetto in seguito a occuparsi di potenziali bug,

  • o contrassegnare la classe sealedin modo da mostrare esplicitamente ai futuri programmatori che questa classe non è destinata a essere ereditata e che l'annullamento e l'utilizzo come genitore dovrebbero essere eseguiti a proprio rischio.

È una buona idea sigillare il maggior numero possibile di lezioni o il minor numero possibile? Dalla mia esperienza, non esiste una risposta definitiva. Alcuni sviluppatori tendono ad usare sealedtroppo; altri non si preoccupano di come la classe verrebbe ereditata e del problema che può causare. Dato tale utilizzo, il problema è simile a quello che consiste nel determinare se i programmatori dovrebbero usare due o quattro spazi per il rientro: non esiste una risposta giusta.


Va bene ... Scusa se sembro di nuovo aggressivo, ma voglio solo essere chiaro e deciso qui ... Posso solo capire cosa hai appena scritto in uno dei due modi, se dovessi scrivere un tl;drqui. È "No, non esiste una sola buona ragione" o "Penso che non ci sia una buona ragione, ma non lo so neanche io." . Per me "nessuna risposta definitiva" è una di queste.
Cregox,

6
sealedè usato per indicare che lo scrittore della classe non l'ha progettato per essere ereditato. Questa è la tua unica buona ragione.
Robert Harvey,

Questo è un buon motivo per darti una bicicletta senza luci e far rispettare, in qualche modo, non puoi aggiungere luci.
Cregox,

2
@Cawas Come? In tale contesto, non è importante per il costruttore di biciclette garantire che la bici non abbia una luce, ma spesso è importante per l'utente di un tipo garantire che l'implementazione sia un'implementazione particolarmente precisa. Imponi i vincoli di cui hai bisogno. In alcuni casi le persone possono aggiungere un vincolo che non è effettivamente necessario; hai fornito un esempio di questo. Solo perché il vincolo viene utilizzato in modo improprio in un punto non significa che non si dovrebbe mai vincolare nulla.
Servito il

1
Anche la sicurezza è un motivo per usarla! Prendi in considerazione un'applicazione sandbox che tenta di accedere a un file. La sandbox potrebbe testare le stringhe del nome file, ma cosa succede se un utente malintenzionato potrebbe inviarti un oggetto mutabile String e poi lo muteranno dopo il controllo di sicurezza ma prima dell'I / O? Credo che questo tipo di scenario sia il motivo per cui Java Stringè contrassegnato final(simile a sealed) e scommetto che la stessa logica è alla base di alcune decisioni C #.
Darien,

4

Quando una classe viene sigillata, consente al codice che utilizza quel tipo di sapere esattamente con cosa hanno a che fare.

Ora in C # stringè sealed, non puoi ereditare da esso, ma supponiamo per un secondo che non sia così. Se lo facessi, allora qualcuno potrebbe scrivere una lezione come questa:

public class EvilString// : String
{
    public override string ToString()
    {
        throw new Exception("I'm mean");
    }
    public override bool Equals(object obj)
    {
        return false;
    }
    public override int GetHashCode()
    {
        return 0;
    }
}

Questa sarebbe ora una classe di stringhe che sta violando tutti i tipi di proprietà che i designer stringsapevano essere vere. Sapevano che il Equalsmetodo sarebbe stato transitivo, non lo è. Diamine, questo metodo uguale non è nemmeno simmetrico, in quanto una stringa potrebbe essere uguale ad essa ma non sarebbe uguale a quella stringa. Sono sicuro che ci sono tutti i tipi di programmatori che hanno scritto codice partendo dal presupposto che il ToStringmetodo stringnon genererà un'eccezione per valori non nulli. Ora sarai in grado di violare tale presupposto.

Ci sono un numero qualsiasi di altre classi per cui potremmo fare questo, e ogni sorta di altre ipotesi che potremmo violare. Se si rimuove la funzione della lingua persealedquindi i progettisti del linguaggio ora devono iniziare a contabilizzare cose come queste in tutto il loro codice di biblioteca. Devono eseguire tutti i tipi di controlli per assicurarsi che i tipi estesi dei tipi che desiderano utilizzare vengano scritti "correttamente", il che può essere una cosa molto costosa da fare (sia in fase di sviluppo che in fase di esecuzione). Essendo in grado di sigillare una classe, possono assicurarsi che ciò non sia possibile e che qualsiasi affermazione fatta sui dettagli di implementazione dei propri tipi non possa essere violata, ad eccezione di quei tipi che sono stati progettati intenzionalmente per essere estesi. Per quei tipi progettati per essere estesi, il codice della lingua deve essere molto più difensivo su come gestirli.


Ma sei in grado di violare tale presupposto nel tuo codice . Non è come prendere la fonte di String e modificarla. I progettisti non dovrebbero tenerne conto perché si tratta di 1 foglia, 1 filiale, 1 cliente che lo utilizza a proprio rischio e discrezione. Non si diffonderà da lì, a meno che altri clienti preferiscano farlo. E così via.
Cregox,

3
@Cawas E se viene generata un'eccezione in un momento imprevisto e una risorsa viene trapelata di conseguenza, o una classe viene lasciata in uno stato indeterminato e funziona in modo inappropriato? Questo caso è un po 'sciocco, ma potrebbe facilmente accadere che qualcuno scriva un'implementazione che ritengono sensata, ma occasionalmente lancia quando non dovrebbe, o non funziona con determinati valori. Si lamenteranno quindi quando il codice della lingua non funziona. È preferibile non lasciare che le persone facciano cose che la lingua non sarà in grado di supportare.
Servito il

In ogni caso stai parlando di costruire un compilatore. Ci sono molte di queste sealedfunzionalità integrate che non sono esposte per noi da usare. Non spiega ancora perché usarlo al di fuori di un ambito così ristretto e, essendo stretto come il codice del compilatore , non spiega nemmeno l' sealedesistenza.
Cregox,

2
@Cawas Il stringtipo non è il codice del compilatore. Fa parte del codice della lingua. Completamente differente. In ogni caso, ho appena scelto un esempio. Puoi prendere quasi tutte le classi sigillate nell'intero BCL e usarle come esempio.
Servito il

4
@Cawas: Penso che ciò che potresti perdere qui sia l'aspetto dell'assistenza clienti. Se permetti a una classe di essere ereditabile, i clienti erediteranno da essa e ti chiameranno quando si interrompe. Puoi dire loro tutto il giorno che ereditano da quella classe a loro rischio e pericolo, ma riceverai comunque la chiamata, perché hai permesso loro di ereditare da essa, quindi presumono che sia sicuro farlo.
Robert Harvey,

3

C'è qualche buona ragione per usare sigillato?

Enh? Non spesso. Vi utilizzato solo sigillato quando ho un tipo immutabile (o qualche altra limitazione) che realmente realmente deve rimanere immutabile e non posso eredi fiducia a furfill tale requisito senza introdurre sottili, insetti catastrofica nel sistema.

Supponiamo che ci sia una buona ragione per usare sigillato e dovremmo usarlo come predefinito per tutto, cosa facciamo con l'eredità?

Usiamo l'ereditarietà per quelle cose che non sono predefinite. Anche se la composizione è favorita dall'eredità (e lo è), ciò non significa che l'ereditarietà debba essere scartata. Significa che l'ereditarietà ha alcuni problemi intrinseci che introduce nella progettazione e nella manutenibilità del codice e nella composizione fa la stessa cosa con (in generale) meno problemi. E significa che anche se la composizione è favorita, l'ereditarietà è buona per alcuni sottogruppi di problemi.

Non intendo essere troppo cattivo, ma se hai appena sentito parlare di SOLID e unit test, forse dovresti uscire dal sottotitolo del tuo rock e scrivere effettivamente il codice. Le cose non sono nette, e raramente "farai sempre X" o "non usare mai Y" o "Z è la cosa migliore" sarà la strada giusta (come sembra che tu graviti sulla base delle opinioni della tua domanda). Mentre scrivi il codice puoi vedere casi in cui sealedpotrebbe essere buono e casi in cui ti fa soffrire, proprio come qualsiasi altro compromesso.


Per me, questo e il "per evitare di dover sostenere l'eredità ai clienti" che Robert non vuole elaborare sono le risposte più promettenti ... Forse potresti approfondire di più su quei casi in cui usi sealed, per favore?
Cregox,

@Cawas - Non sono sicuro di poterlo fare bene. Lo faccio molto raramente, ed è spesso un compromesso in cui la garanzia che qualcosa rimanga immutabile (per rendere ottimizzazioni delle prestazioni, semplificazione del design) vale l'incapacità di ereditare dall'oggetto.
Telastyn,

Questo è figo. Dunk l'ha già schiacciato! : P Grazie mille per la risposta. E tu eri l'unico a raccogliere i miei "suggerimenti sottili" sulla mia esperienza. Sembra che la gente pensasse che ne sapessi di più, non lo so ... Ma vorrei "solo codificare" mi avrebbe portato fuori da questa roccia. Forse applicherò quei concetti in qualche modo, non proceduralmente come probabilmente dovrei.
Cregox,

3

Prima di tutto, dovresti leggere il post di Eric Lippert sul perché Microsoft sigilli le loro classi.

http://blogs.msdn.com/b/ericlippert/archive/2004/01/22/61803.aspx

In secondo luogo, esiste la parola chiave sigillata per fare esattamente ciò che fa: prevenire l'ereditarietà. Esistono molte situazioni in cui si desidera impedire l'ereditarietà. Considera una classe di cui hai una collezione. Se il tuo codice dipende dal fatto che quella classe funzioni in un modo particolare, non vuoi che qualcuno sovrascriva uno dei metodi o delle proprietà in quella classe e causi il fallimento dell'applicazione.

In terzo luogo, l'uso del sigillato incoraggia la composizione rispetto all'eredità, che è una buona abitudine da prendere in considerazione. L'uso della composizione sull'eredità significa che non puoi infrangere il principio di sostituzione di Liskov e stai seguendo il principio di apertura / chiusura. sealedè quindi una parola chiave che ti aiuta a seguire due dei cinque principi più importanti della programmazione oo. Direi che lo rende una funzionalità molto preziosa.


La prima parte è già evidenziata nei commenti alla domanda. La seconda parte è solo più ragionamento senza reali cause. La terza parte, anche se già affrontata altrove, potrebbe avere qualcosa da fare. Mi concentrerei su quello.
Cregox,

il terzo punto non incoraggia la composizione rispetto all'eredità, elimina completamente l'eredità come opzione, anche se questa è stata la scelta complessiva migliore.
Michael Shaw,

Dipende se controlli la base di codice o meno. Se sigilli le classi, puoi sempre aprirle in seguito, se necessario.
Stephen,

2

Penso che questa domanda non abbia una risposta obiettiva e che tutto dipende dalla tua prospettiva.

Da un lato, alcune persone vogliono tutto "aperto" e l'onere di garantire che tutto funzioni correttamente è sulla persona che estende la classe. Questo è il motivo per cui le classi sono aperte all'ereditarietà per impostazione predefinita. E perché i metodi Java sono tutti virtuali per impostazione predefinita.

D'altra parte, alcuni vogliono che tutto sia chiuso per impostazione predefinita e che fornisca opzioni per aprirlo. In questo caso, è l'autore della classe base che deve assicurarsi che tutto ciò che rende "aperto" sia sicuro da usare in qualsiasi modo immaginabile. Questo è il motivo per cui in C # tutti i metodi non sono virtuali per impostazione predefinita e devono essere dichiarati virtuali per essere sostituiti. È anche per quelle persone, che devono essere il modo di eludere le impostazioni predefinite "aperte". Come rendere la classe sigillata / finale, perché vedono qualcuno derivare dalla classe un grosso problema per il design della propria classe.


Questo è più simile! Questo potrebbe essere un buon motivo ... "Perché le persone vogliono chiuderlo". Ed è anche quello che sto cercando di dire nella domanda: sembra che le classi non virtuali in C ++ possano essere ignorate. sealednon si può. Come possiamo ereditare da loro? Tutto quello che leggo è che non possiamo. Mai. Non lo so. Sono stato su questo argomento per 4 mesi, da quando ho sentito parlare per la prima volta di sigillato. E io ancora non so come farlo nel modo giusto, quando ho bisogno di modificare nulla su una classe sigillata. Quindi, non vedo alcuna "opzione per aprirlo"!
Cregox,

4
Questo non è il motivo per cui i metodi di classe C ++ non sono virtuali per impostazione predefinita. Rendere virtuale un metodo significa che ci deve essere un overhead aggiuntivo nella tabella di ricerca del metodo e C ++ ha la filosofia che si paga solo per l'overhead quando si desidera la funzionalità.
Michael Shaw,

@Ptolemy Ok, l'ho rimosso. Non avrei mai dovuto scriverlo, perché sapevo che le persone iniziano a lamentarsene.
Euforico,

ehi, apprezzo completamente che se vuoi affermare che le persone vogliono scrivere classi chiuse per impostazione predefinita, e devi scegliere attivamente di aprirle, dovrai stringere a botte
Michael Shaw,

L'IMO è estremamente simile ai dibattiti privati ​​/ protetti / pubblici quando si tratta di API: dipende fortemente da chi controlla la classe, da chi vuole ereditare la classe, dalla comunicazione tra i due e dalla frequenza con cui escono nuove versioni.
Darien,

-2

il problema con sigillato in C # è che è piuttosto definitivo. In 7 anni di sviluppo commerciale in C #, l'unico posto in cui l'ho visto utilizzato è nelle classi di Microsoft .NET in cui ritengo di avere un motivo legittimo per estendere una classe di framework per implementare un comportamento adattato e, poiché la classe è stata sigillata, non ho potuto .

È impossibile scrivere una lezione pensando a ogni possibile modo in cui potrebbe essere usato e decidendo che nessuno di loro è legittimo. Allo stesso modo se la sicurezza del framework dipende dalla classe che non viene ereditata, allora hai un difetto di progettazione della sicurezza.

Quindi, in conclusione, sono fermamente convinto che sigillato non abbia alcuno scopo utile e nulla di ciò che ho letto qui finora ha cambiato tale punto di vista.

Vedo che finora ci sono stati tre argomenti che giustificano il suggellamento posto finora.

  1. L'argomento 1 è che elimina una fonte di bug quando le persone ereditano dalle classi e quindi hanno un maggiore accesso agli interni di quella classe senza realmente capirne correttamente gli interni.

  2. L'argomento 2 è che se estendi una classe microsoft e poi microsoft implementa una correzione di bug in quella classe ma la tua estensione si basava su quel bug allora il tuo codice è rotto, microsoft ottiene la colpa e sigillato impedisce che

  3. L'argomento 3 è che come sviluppatore della classe, è una mia scelta se permetterti di estenderlo, come parte del mio progetto della classe.

L'argomento 1 sembra essere un argomento secondo cui il programmatore finale non sa come usare il mio codice. Questo può essere il caso, ma se mi consenti ancora di accedere all'interfaccia degli oggetti, è ancora vero che sto usando il tuo oggetto e sto effettuando chiamate senza capire come usarlo, e quindi posso fare altrettanto danno in quel modo . Questa è una debole giustificazione della necessità di sigillare.

Capisco da dove viene la base fattuale per arg 2. In particolare, quando Microsoft ha effettuato ulteriori controlli del sistema operativo sulle chiamate API Win32 per identificare le chiamate non valide, il che ha migliorato la stabilità generale di Windows XP rispetto a Windows NT, ma a breve termine che molte app sono state interrotte al rilascio di Windows XP. Microsoft lo ha risolto inserendo "regole" affinché questi controlli dicessero, ignorare quando l'app X infrange questa regola, è un bug noto

L'argomento 2 è un argomento scarso perché, nella migliore delle ipotesi, sigillato non fa praticamente alcuna differenza, perché se c'è un bug nella libreria .NET non hai altra scelta che trovare un modo per aggirare il problema, e quando esce la correzione di Microsoft, è molto probabile significa che il tuo lavoro attorno al quale dipende dal comportamento rotto ora è rotto. Indipendentemente dal fatto che tu abbia aggirato questo problema utilizzando l'ereditarietà o con qualche altro codice wrapper aggiuntivo, quando il codice è stato risolto, il tuo lavoro verrà interrotto.

L'argomento 3 è l'unico argomento che ha una sostanza per giustificare se stesso. Ma è ancora debole. Va semplicemente contro il riutilizzo del codice.


2
/ me invia un'e-mail a microsoft, per favore puoi rimuovere la classe X per me e spedire una nuova versione di .NET. cordiali saluti, .... Come ho detto, l'unica volta nello sviluppo commerciale che ho visto una classe sigillata, non è stato possibile annullarla.
Michael Shaw,

6
It is impossible to write a class thinking about every possible way it could be used- Questo è esattamente il motivo per cui molte classi Framework sono sigillate ... Elimina la necessità di pensare a ogni possibile modo in cui qualcuno potrebbe estendere la classe.
Robert Harvey,

5
Se potessi dissimularlo, non ci sarebbe molto senso sigillarlo, vero?
Robert Harvey,

2
@Ptolemy Consentire alle persone di estendere la tua lezione è una caratteristica . Uno che consuma una notevole quantità di sforzi di sviluppo. È una caratteristica che vale la pena giustificare solo se l'autore della classe può vedere abbastanza benefici in potenziali estensioni da giustificare lo sforzo. Se non sono in grado di giustificare lo sforzo, e quindi il tipo e i suoi utenti non sono creati per supportare l'estensione, è importante prevenirlo, altrimenti si sarebbe tecnicamente in grado di estendere il tipo, ma è improbabile che funzioni correttamente quando lo fai.
Servito il

2
@Cawas: Stai solo diventando difficile.
Robert Harvey,


-8

Come evidente dalla mia domanda, qui non sono un esperto. Ma non vedo alcun motivo per sealedesistere.

Sembra fatto per aiutare gli architetti di codice a progettare un'interfaccia. Se vuoi scrivere una classe che uscirà allo stato brado e molte persone erediteranno da essa, modificare qualsiasi cosa in quella classe può romperla per troppe persone. Quindi possiamo sigillarlo e nessuno può ereditare. "Problema risolto".

Bene, sembra "coprire un posto e scoprirne un altro". E non sta nemmeno risolvendo un problema, sta semplicemente eliminando uno strumento : l' eredità. Come ogni strumento, ha molti usi e ereditare da una classe instabile è un rischio che si prende. Chiunque abbia preso quel rischio dovrebbe saperlo meglio.

Forse potrebbe esserci una parola chiave stable, quindi la gente saprebbe che è più sicuro ereditarla.


2
"Problema risolto" - Esatto.
Robert Harvey,

@RobertHarvey Non è risolto, come spiegato nel paragrafo successivo.
Cregox,

8
Sei solo arrabbiato perché non puoi estendere la classe. Ciò non significa che sealednon sia uno strumento utile per i progettisti di framework. Le classi in un quadro dovrebbero essere scatole nere; non dovresti conoscere gli interni di una classe per poterlo usare correttamente. Eppure è esattamente ciò che richiede l'eredità.
Robert Harvey,

Non ho mai detto che non sia utile. Dico che non vedo il suo utilizzo e sottolineo il perché. Ti prego, ti prego, dammi una buona ragione per usarlo! Anche se è solo "perché voglio seguire un modello di design chiuso", va bene. Non vedo nessuno dare questo motivo, esplicitamente.
Cregox,

7
La buona ragione è che non devi supportare l'eredità in una classe sigillata.
Robert Harvey,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.