2011-08-30 18 views

risposta

29

Ecco un esempio di perché che non ha senso essere in grado di sostituire la visibilità:

interface someI 
{ 
    void doYourWork(); 
} 
public class A : someI 
{ 
    public void doYourWork() 
    { 
     //... 
    } 
} 

public class B : someI 
{ 
    private void doYourWork() 
    { 
     //... 
    } 
} 
void Main() 
{ 
    List<someI> workers = getWorkers(); 
    foreach(var worker in workers) 
     worker.doYourWork(); 
} 

Cosa succede quando il lavoratore è di tipo B? Stai chiamando un metodo come se fosse pubblico, ma è un metodo privato. Se vuoi questa funzionalità, allora non è davvero un metodo privato vero?

Se desideri solo che sia pubblico, quando si fa riferimento tramite l'interfaccia, allora si può definire come tale:

public class B : someI 
{ 
    void someI.doYourWork() 
    { 
     //... 
    } 
} 

e si finisce con questo:

var b = new B(); 
b.doYourWork(); // Not accessible 
((someI)b).doYourWork(); // Accessible 
+3

Suggerirei che per le classi non sigillate, le interfacce le cui implementazioni non esporranno i membri della classe pubblica con gli stessi nomi e firme dovrebbero essere implementate usando membri virtuali protetti; sfortunatamente, il più vicino può arrivare a farlo in C# è avere un'implementazione dell'interfaccia semplicemente chiamando un metodo virtuale protetto. Altrimenti, se una classe derivata re-implementa un'interfaccia non ci sarà modo di chiamare l'implementazione genitore. – supercat

+1

@supercat Forse è solo presto, ma non sono sicuro di seguirti; cosa intendi con 'Altrimenti, se una classe derivata re-implementa un'interfaccia non ci sarà modo di chiamare l'implementazione genitore? Perché vuoi avere un metodo protetto che implementa un'interfaccia (non sarai in grado di accedervi tramite l'interfaccia in questo caso, solo in classi derivate che potrebbero non sapere nemmeno quali interfacce stanno implementando) – Rob

+2

In vb.net , si può dire: 'Sovraccarico protetto DoSomethingImpl() Implementa IDoSomething.DoSomething'; il codice esterno sarà in grado di chiamare tale metodo solo tramite l'interfaccia, ma una classe derivata sarà in grado di sovrascrivere il metodo e, all'interno dell'override, chiamare il metodo genitore. In C#, sarebbe utile poter usare allo stesso modo un metodo protetto per implementare un'interfaccia, ma i responsabili delle specifiche non consentono questa opzione. Il più vicino possibile sarebbe implementare esplicitamente l'interfaccia con un metodo che chiamerebbe il metodo protetto 'DoSomethingImpl()'. Si noti che ... – supercat

20

I metodi devono essere implementati public perché devono essere richiamabili tramite l'interfaccia, quindi da dove l'interfaccia è accessibile come tipo.

Hai alcune opzioni qui per "cambia" la visibilità di tale metodo. Dato:

public interface IFoo 
{ 
    bool IsFoo(); 
} 

A. Implementare il metodo explicitly

public class Foo : IFoo 
{ 
    bool IFoo.IsFoo() { return true; } 
} 

Il metodo sarà disponibile solo tramite l'interfaccia

B. Modifica la visibilità (IFoo in questo caso). l'interfaccia

Definire l'interfaccia come internal anziché public. Di conseguenza, tuttavia, Foo dovrà essere internal.

+0

in altre lingue come come vb.net, non è richiesta alcuna particolare accessibilità per un metodo che implementa un'interfaccia. C# richiede che le implementazioni dell'interfaccia implicita debbano essere pubbliche perché non ci sono altre parole chiave o notazioni per indicare che un membro della classe con nome deve essere considerato come un'implementazione dell'interfaccia. – supercat

5

Richiedere che un'implementazione dell'interfaccia sia pubblica è semplicemente un requisito logico. Quando implementi un'interfaccia, stai dicendo al compilatore "Ehi, io implemento ogni metodo su questa interfaccia". Quindi rendere il metodo privato non lo rende più accessibile e logicamente non implementato. Le interfacce fungono da contratto per il codice che utilizza il tuo oggetto dicendo che puoi sempre chiamare qualsiasi metodo definito nell'interfaccia sul mio oggetto. Se il metodo di implementazione fosse privato, ciò non sarebbe più vero.

Se si desidera nascondere la propria implementazione, ad esempio Intellisense, è possibile implementare il metodo in modo esplicito come @Bryan menziona.

+0

"Le interfacce fungono da contratto per il codice che utilizza l'oggetto dicendo che puoi sempre chiamare qualsiasi metodo definito nell'interfaccia sul mio oggetto." Questo non è assolutamente vero. Significa che è possibile eseguire il cast di un'istanza della classe sull'interfaccia e _quindi_ chiamare i metodi dell'interfaccia tramite il riferimento all'interfaccia. Questo è il contratto, NON la possibilità di chiamare i metodi dell'interfaccia senza prima eseguire il casting nell'interfaccia. Ovviamente dovresti di solito esporre i metodi dell'interfaccia senza richiedere il cast, ma questo non è né un requisito tecnico, né sempre un requisito logico. – Darryl

Problemi correlati