2010-05-05 5 views
6

In C++, è possibile effettuare le seguenti operazioni:forzare l'uso dell'interfaccia al posto di concreta attuazione nella dichiarazione (NET)

class base_class 
{ 
public: 
    virtual void do_something() = 0; 
}; 

class derived_class : public base_class 
{ 
private: 
    virtual void do_something() 
    { 
     std::cout << "do_something() called"; 
    } 
}; 

Il derived_class l'override del metodo do_something() e rende private. L'effetto è, che l'unico modo per chiamare questo metodo è simile a questo:

base_class *object = new derived_class(); 
object->do_something(); 

Se si dichiara l'oggetto come di tipo derived_class, non è possibile chiamare il metodo, perché è privato:

derived_class *object = new derived_class(); 
object->do_something(); 
// --> error C2248: '::derived_class::do_something' : cannot access private member declared in class '::derived_class' 

Penso che sia abbastanza carino, perché se si crea una classe astratta che viene utilizzata come interfaccia, è possibile assicurarsi che nessuno dichiari accidentalmente un campo come tipo concreto, ma utilizzi sempre la classe di interfaccia.

Poiché in C#/.NET in generale, non è consentito limitare l'accesso da public a private quando si sostituisce un metodo, esiste un modo per ottenere un effetto simile qui?

risposta

14

Se si implementa esplicitamente un'interfaccia, questo incoraggerà almeno le persone a utilizzare il tipo di interfaccia nella dichiarazione.

interface IMyInterface 
{ 
    void MyMethod(); 
} 

class MyImplementation : IMyInterface 
{ 
    void IMyInterface.MyMethod() 
    { 
    } 
} 

Si vedrà solo dopo la colata MyMethod l'istanza di IMyInterface. Se la dichiarazione utilizza il tipo di interfaccia, non è necessaria alcuna trasmissione negli usi successivi.

MSDN page on explicit interface implementation (grazie Luca, me un paio di secondi ^^ parate)

IMyInterface instance = new MyImplementation(); 
instance.MyMethod(); 

MyImplementation instance2 = new MyImplementation(); 
instance2.MyMethod(); // Won't compile with an explicit implementation 
((IMyInterface)instance2).MyMethod(); 
+0

Questo effetto è ciò che voglio, grazie. – gammelgul

+0

+1 Ho appena imparato qualcosa di nuovo! – BritishDeveloper

+0

+1 Grazie per questo, ho anche imparato qualcosa di nuovo! – Deano

2

È in grado di ridurre la disponibilità di un metodo contrassegnandolo come new.

L'esempio da MSDN's CA2222: Do not decrease inherited member visibility:

using System; 
namespace UsageLibrary 
{ 
    public class ABaseType 
    { 
     public void BasePublicMethod(int argument1) {} 
    } 
    public class ADerivedType:ABaseType 
    { 
     // Violates rule: DoNotDecreaseInheritedMemberVisibility. 
     // The compiler returns an error if this is overridden instead of new. 
     private new void BasePublicMethod(int argument1){}  
    } 
} 

Questo è davvero più interessante come un esercizio accademico; se il tuo codice dipende veramente dal fatto di non essere in grado di chiamare BasePublicMethod su ADerivedType, questo è un segnale di avvertimento di un design dubbio.

4

Si può fare questo nel mondo .Net troppo, utilizzando explicit interface implementation

A titolo di esempio, BindingList<T> implementa IBindingList, ma si deve gettarlo ai IBindingList per vedere il metodo.

+1

E 'noto come implementazione esplicita: http://msdn.microsoft.com/en-us/library/aa288461.aspx – LukeH

+0

@ Luca Grazie per il link, ho faticato a trovarlo :) –

0

Il problema con questa strategia, dovrebbe essere implementato, è che il metodo non è veramente privato. Se si dovesse emettere un riferimento a base_class, il metodo è ora pubblico. Poiché si tratta di un metodo virtuale, il codice utente verrà eseguito derived_class::do_something() sebbene sia contrassegnato come privato.

+2

In questo scenario, questo non è visto come un bug, ma come una caratteristica. – sbi

Problemi correlati