Come riutilizzare il codice quando l'ereditarietà multipla non è un'opzione?
-
05-07-2019 - |
Domanda
Vorrei utilizzare alcuni metodi di un paio delle mie vecchie classi testate nella mia nuova classe che sto creando. Sfortunatamente, C # non supporta l'ereditarietà multipla. Come riutilizzo il codice di queste vecchie classi? Li creo semplicemente come oggetti membro? o Ho altre opzioni?
Soluzione
Generalmente, usare la composizione invece dell'ereditarietà è la via da seguire, sì. Se potessi dare un esempio concreto del tipo di cose che intendi, ciò renderebbe più semplice aiutare a trovare l'approccio appropriato: non è sempre lo stesso.
Altri suggerimenti
Usarli come oggetti membro dovrebbe essere una buona idea. Quindi puoi anche esporre solo i metodi di interesse e adattarli se necessario.
Puoi quindi ricrearli come metodi di estensione quando funzionano sullo stesso tipo.
public static void MyMethod( this MyType target ){}
MyType.MyMethod()
come indicato di seguito, se hai una classe che deriva da MyType o più comuni implementa l'interfaccia su cui funziona il metodo di estensione, l'estensione funziona per quelli.
public class MyDerived : MyType{}
MyDerived.MyMethod()
Tecnicamente, C # implementa l'ereditarietà multipla interfaccia , ma non multipla implementazione ereditarietà.
Il problema con l'ereditarietà dell'implementazione multipla è che porta a situazioni come il problema del diamante .
È possibile simulare l'ereditarietà multipla dell'implementazione utilizzando l'interfaccia multipla eredità e composizione, che è vicino a ciò che hai descritto come creazione gli oggetti che desideri riutilizzare " come oggetti membro " ;. Quello che non vuoi fare, tuttavia è esporre comportamenti non necessari dal tipo di wrapping.
Di seguito è riportato un diagramma di classe che mostra il principio di base del multiplo eredità attraverso la composizione:
Ereditarietà multipla http://www.freeimagehosting.net/uploads/cb219cefba.jpg
Lo svantaggio di ciò è che saranno necessarie eventuali modifiche all'interfaccia IBreeper corrispondenti modifiche a Breeper e viceversa.
Facendo un passo indietro, però, è necessario esaminare attentamente i motivi di componendo le vecchie classi. È per:
-
Migliora o intensifica il comportamento esistente. Dovresti quindi prendere in considerazione il Proxy Pattern ;
-
Crea un " sportello unico " per tutto il tuo comportamento. Dovresti davvero farlo solo se il tuo SuperFuddler è coeso (ovvero, tutti i comportamenti esposti sono allineati), altrimenti ti sposterai in God God situazione che non favorisce la mantenibilità;
-
Presenta un'interfaccia più coerente con una modalità d'uso richiesta da una determinata classe di client del tuo SuperFuddler. In questo caso, dovresti prendere in considerazione il Pattern adattatore .
Puoi simularlo abbastanza facilmente in questo modo:
public interface IFoo {
void DoFoo();
}
public class Foo : IFoo {
public void DoFoo() { Console.Write("Foo"); }
}
public class Bar {
public void DoBar() { Console.Write("Bar"); }
}
public class FooBar : IFoo, Bar {
private IFoo baseFoo = new Foo();
public void DoFoo() { baseFoo.DoFoo(); }
}
//...
FooBar fooBar = new FooBar();
fooBar.DoFoo();
fooBar.DoBar();
se li hai sviluppati come componente, usali non ereditati da loro