Miembros no públicos para interfaces C #

En C #, cuando implementa una interfaz, todos los miembros son implícitamente públicos. ¿No sería mejor si pudiéramos especificar el modificador de accesibilidad ( protected , internal , excepto private por supuesto), o deberíamos usar una clase abstracta en su lugar?

Si una interfaz es interna, todos sus miembros serán internos al ensamblado. Si una interfaz anidada está protegida, solo las subclases de la clase externa podrían acceder a esa interfaz.

Los miembros internos para una interfaz fuera de su ensamblaje de statement serían inútiles, al igual que los miembros protegidos para una interfaz fuera de su clase exterior declarante.

El objective de una interfaz es describir un contrato entre un tipo de implementación y los usuarios de la interfaz. A las personas que llaman desde afuera no les importará y no deberían preocuparse por la implementación, que es para lo que son los miembros internos y protegidos.

Para los miembros protegidos que son llamados por una clase base, las clases abstractas son el camino a seguir para especificar un contrato entre las clases base y las clases que heredan de ellas. Pero en este caso, los detalles de implementación suelen ser muy relevantes, a menos que se trate de una clase abstracta pura degenerada (en la que todos los miembros son abstractos), en cuyo caso los miembros protegidos son inútiles. En ese caso, vaya con una interfaz y guarde la clase base única para implementar tipos para elegir.

Puede ocultar la implementación de una interfaz declarando explícitamente el nombre de la interfaz antes del nombre del método:

 public interface IInterface { public void Method(); } public class A : IInterface { public void IInterface.Method() { // Do something } } public class Program { public static void Main() { A o = new A(); o.Method(); // Will not compile ((IInterface)o).Method(); // Will compile } } 

No tendría sentido. Una interfaz es un contrato con el público que admite esos métodos y propiedades. Quédate con las clases abstractas.

Todas las respuestas aquí más o menos dicen que así es como deben ser las interfaces, son especificaciones públicas universales.

Siendo este el tema más discutido, permítanme publicar dos excelentes respuestas que encontré en SO cuando surgió esta pregunta.

Esta respuesta proporciona un ejemplo de cómo puede ser absurdo tener especificadores de acceso no uniformes para los miembros de la interfaz en las clases derivadas. Código siempre mejor que las descripciones técnicas.

Para mí, la cosa más condenatoria sobre los miembros de la interfaz pública forzada es que la interfaz en sí misma puede ser interna a un ensamblado, pero los miembros que expone deben ser públicos. Jon Skeet explica que eso es por diseño, lamentablemente .

Eso plantea la pregunta de por qué no se diseñaron las interfaces para que tengan definiciones no públicas para los miembros. Eso puede hacer que el contrato sea flexible. Esto es bastante útil cuando se escriben ensamblajes en los que no se desea que miembros específicos de las clases estén expuestos fuera del ensamblaje. No se por que.

Una interfaz es un contrato al que se adhieren todas las clases implementadoras. Esto significa que deben adherirse a todo o nada de eso.

Si la interfaz es pública, cada parte de ese contacto tiene que ser pública, de lo contrario, significaría para amigo / clases internas y una cosa diferente para todo lo demás.

Utilice una clase base abstracta o (si es posible y práctico) un método interno de extensión en la interfaz .

Puede ocultar casi todo el código implementado por las interfaces en ensambles externos.

 interface IVehicle { void Drive(); void Steer(); void UseHook(); } abstract class Vehicle // :IVehicle // Try it and see! { ///  /// Consuming classes are not required to implement this method. ///  protected virtual void Hook() { return; } } class Car : Vehicle, IVehicle { protected override void Hook() // you must use keyword "override" { Console.WriteLine(" Car.Hook(): Uses abstracted method."); } #region IVehicle Members public void Drive() { Console.WriteLine(" Car.Drive(): Uses a tires and a motor."); } public void Steer() { Console.WriteLine(" Car.Steer(): Uses a steering wheel."); } ///  /// This code is duplicated in implementing classes. Hmm. ///  void IVehicle.UseHook() { this.Hook(); } #endregion } class Airplane : Vehicle, IVehicle { protected override void Hook() // you must use keyword "override" { Console.WriteLine(" Airplane.Hook(): Uses abstracted method."); } #region IVehicle Members public void Drive() { Console.WriteLine(" Airplane.Drive(): Uses wings and a motor."); } public void Steer() { Console.WriteLine(" Airplane.Steer(): Uses a control stick."); } ///  /// This code is duplicated in implementing classes. Hmm. ///  void IVehicle.UseHook() { this.Hook(); } #endregion } 

Esto probará el código.

 class Program { static void Main(string[] args) { Car car = new Car(); IVehicle contract = (IVehicle)car; UseContract(contract); // This line is identical... Airplane airplane = new Airplane(); contract = (IVehicle)airplane; UseContract(contract); // ...to the line above! } private static void UseContract(IVehicle contract) { // Try typing these 3 lines yourself, watch IDE behavior. contract.Drive(); contract.Steer(); contract.UseHook(); Console.WriteLine("Press any key to continue..."); Console.ReadLine(); } } 

Las interfaces no tienen modificadores de acceso en sus métodos, dejándolos abiertos a cualquier modificador de acceso apropiado. Esto tiene un propósito: permite a otros tipos inferir qué métodos y propiedades están disponibles para un objeto que sigue una interfaz. Darles acceso interno protegido / derrota el propósito de una interfaz.

Si insistes en que debes proporcionar un modificador de acceso para un método, ya sea que lo dejes fuera de la interfaz, o como dijiste, usa una clase abstracta.

Estoy familiarizado con Java en lugar de C #, pero ¿por qué querría un miembro privado dentro de una interfaz? No podría tener ninguna implementación y sería invisible para implementar clases, por lo que sería inútil. Existen interfaces para especificar el comportamiento. Si necesita un comportamiento predeterminado, use una clase abstracta.

En mi opinión, esto viola la encapsulación. Tengo que implementar un methos como público y luego implementar una interfaz. No veo ninguna razón para forzar al público en una clase que implemente la interfaz. (do#)