2011-08-30 30 views

Respuesta

29

He aquí un ejemplo de por qué que no tiene sentido que sea capaz de anular la visibilidad:

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(); 
} 

¿Qué pasa cuando el trabajador es de tipo B? Llamas a un método como si fuera público, pero es un método privado. Si quieres esta funcionalidad, entonces no es realmente un método privado ¿verdad?

Si sólo quiere que sea pública cuando se hace referencia a través de su interfaz, entonces se puede definir como tal:

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

Y terminar con esto:

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

Sugeriría que para las clases no selladas, las interfaces cuyas implementaciones no van a exponer a los miembros de la clase pública con los mismos nombres y firmas se implementen usando miembros virtuales protegidos; desafortunadamente, lo más cercano que se puede hacer en C# es tener una implementación de interfaz simplemente llamar a un método virtual protegido. De lo contrario, si una clase derivada vuelve a implementar una interfaz, no habrá forma de llamar a la implementación principal. – supercat

+1

@supercat Tal vez sea pronto, pero no estoy seguro de que te sigo; ¿A qué te refieres con 'De lo contrario, si una clase derivada implementa nuevamente una interfaz, no habrá forma de llamar a la implementación principal? ¿Por qué quiere tener un método protegido implementando una interfaz (no podrá acceder a ella a través de la interfaz en este caso, solo en clases derivadas que quizás ni siquiera sepa qué interfaces están implementando) – Rob

+2

en vb.net , uno puede decir: 'Sub Subdominio Protegido Implantado() Implementa IDoSomething.DoSomething'; el código externo solo podrá llamar a ese método a través de la interfaz, pero una clase derivada podrá anular el método y, dentro de la anulación, llamar al método padre. En C#, sería útil poder utilizar un método protegido para implementar una interfaz, pero las personas a cargo de la especificación no permiten esa opción. Lo más cercano que se puede llegar a es implementar explícitamente la interfaz con un método que llamaría al método protegido 'DoSomethingImpl()'. Tenga en cuenta que ... – supercat

20

Los métodos deben implementarse public, ya que tienen que ser activables a través de la interfaz, por lo tanto, desde donde se puede acceder a la interfaz como un tipo.

Tiene algunas opciones aquí para "cambiar" la visibilidad de ese método. Dado:

public interface IFoo 
{ 
    bool IsFoo(); 
} 

A. implementar el método explicitly

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

El método sólo estará disponible a través de la interfaz de

B. cambiar la visibilidad de (IFoo en este caso.) la interfaz

Defina la interfaz como internal en lugar de public. Como consecuencia, sin embargo, Foo también tendrá que ser internal.

+0

En otros idiomas tales como vb.net, no se requiere accesibilidad particular para un método que implementa una interfaz. C# requiere que las implementaciones de interfaz implícitas deben ser públicas porque no hay otra palabra clave o notación para indicar que un miembro de clase nombrado también debe considerarse como una implementación de interfaz. – supercat

5

Exigir que una implementación de interfaz sea pública es simplemente un requisito lógico. Cuando implementa una interfaz, le dice al compilador "Oye, implemento todos los métodos en esta interfaz". Por lo tanto, hacer que el método sea privado hace que ya no sea accesible, y lógicamente no se implementa. Las interfaces sirven como un contrato para codificar que usa su objeto diciendo que siempre puede llamar a cualquier método definido en la interfaz en mi objeto. Si el método de implementación fuera privado, eso ya no sería cierto.

Si quiere ocultar su implementación, digamos Intellisense, entonces simplemente puede implementar el método explícitamente como @Bryan menciona.

+0

"Las interfaces sirven como un contrato para codificar que usa su objeto diciendo que siempre puede llamar a cualquier método definido en la interfaz en mi objeto". Eso no es estrictamente cierto. Significa que puede enviar una instancia de la clase a la interfaz y _entonces llamar a los métodos de interfaz a través de la referencia de la interfaz. ESO es el contrato, NO la capacidad de llamar a los métodos de la interfaz sin primera conversión a la interfaz. Por supuesto, normalmente debería exponer los métodos de interfaz sin requerir también el reparto, pero eso no es un requisito técnico ni un requisito lógico. – Darryl

Cuestiones relacionadas