2015-04-21 9 views
6

mi piacerebbe scrivere un
classe X (questo), che
eredita da una (base) possono
eseguire i metodi di B (?) E devono
implementare i membri di C (interfaccia).Esiste qualcosa come una classe che può essere implementata?

L'implementazione di A e C non rappresenta un problema. Ma poiché X non può derivare da più classi, sembra impossibile avere X ereditare la logica di A e B. Si noti che A è la classe base molto importante e B è quasi un'interfaccia ma contiene un comportamento eseguibile. Il motivo per cui non voglio che B sia un'interfaccia è perché il comportamento è lo stesso per ogni classe che lo eredita o lo implementa.

ne ho veramente deve dichiarare B come interfaccia e attuare le stesse identiche 10 righe di codice per ogni X che ha bisogno il comportamento di B?


2 mesi più tardi
Attualmente sto imparando C++ per il suo utilizzo in UE4 (Unreal Engine 4).
Poiché C++ è molto meno stringenti rispetto a C# che contiene in realtà un implementazione IDOM termine modello che descrive questo comportamento: Questi sono chiamati mixin s.

È possibile leggere un paragrafo relativo al mixin C++ here a pagina 9 (secondo paragrafo).

+2

Perché non si eredita B da A o viceversa? –

+3

Perché non puoi usare la composizione qui? Delega i metodi di B a un'istanza di B ...(È molto difficile parlare di questo genere di cose in un modo così astratto. Sarebbe più utile se fornissi un esempio concreto.) –

+0

@ k4rlsson Perché non ogni X richiede B (Lo sviluppatore dovrebbe essere in grado di implementarlo o no) –

risposta

5

ho davvero necessario dichiarare B come interfaccia e attuare le stesse identiche 10 righe di codice per ogni X che ha bisogno l'essere haviour di B?

Sì e no. È necessario creare un'interfaccia B. Ma le implementazioni dei metodi comuni non dovrebbero essere duplicate su tutte le implementazioni dell'interfaccia. Invece, essi dovrebbero andare in un'estensione di classe per l'interfaccia B:

public interface B { 
    void MethodX(); 
    void MethodY(); 
} 
public static class ExtensionsB { 
    public static void MethodZ(this B b) { 
     // Common implementations go here 
    } 
} 

metodi di estensione forniscono un modo per condividere le implementazioni "orizzontalmente", senza avere le vostre classi ereditano da una seconda classe. I metodi di estensione si comportano come se fossero normali metodi della classe:

class X : A, B { 
    public void MethodX() {...} 
    public void MethodY() {...} 
} 
public static void Main(string[] args) { 
    var x = new X(); 
    x.SomeMethodFromA(); 
    x.MethodX(); // Calls method from X 
    x.MethodY(); // Calls method from X 
    x.MethodZ(); // Calls method from ExtensionsB 
} 
+0

Questo è perfetto! Vorrei che aggiungessi l'attributo "class" nella tua classe di estensione. E voglio sottolineare che il metodo di estensione può essere chiamato all'interno della classe usando this.Extension(). Calling Extension() all'interno della classe non funziona. –

1

penso che la soluzione migliore sarebbe quella di chiedere un'istanza di B nel costruttore di A e poi esporre o chiamare i metodi di B come richiesto:

public class X : A, C 
{ 
    private readonly B _b; 

    public X(B b) 
    { 
     _b = b; 
    } 
} 

troverete un sacco di informazioni su questo tipo di approccio se guardi in alto Composition over inheritance

+0

Ciò imporrebbe allo sviluppatore di implementare (dichiarare) B ma voglio che lo sviluppatore abbia la possibilità di scegliere (implementare) da solo. Come se B fosse un'interfaccia –

+0

Non sono proprio sicuro di cosa intendi; implementare e dichiarare non sono la stessa cosa. Potrebbe essere più semplice raccomandare una soluzione se si fornisce un esempio concreto. Ma la composizione è un approccio abbastanza flessibile. – RagtimeWilly

+0

Ci scusiamo per non aver fornito un esempio specifico. Quello che intendevo è che il tuo X SEMPRE dichiara un campo di B. Ma voglio essere in grado di decidere se il mio X usa (implementa) B oppure no. Con la risposta fornita da "dasblinkenlight" ora posso decidere di implementare B sulla mia X o ignorarla. Se scelgo di ignorarlo, non ci sarà alcun campo di B sulla mia X. –