c# - que - no se puede crear una instancia de una interfaz
¿Por qué no puedo tener miembros protegidos de la interfaz? (12)
Al implementar una interfaz, el tipo indica que es compatible con un conjunto específico de métodos. Si alguno de estos métodos no fuera público, no estaría disponible para los llamantes y, por lo tanto, el tipo no admitiría la interfaz como se indica.
¿Cuál es el argumento en contra de declarar miembros de acceso protegido en las interfaces? Esto, por ejemplo, no es válido:
public interface IOrange
{
public OrangePeel Peel { get; }
protected OrangePips Seeds { get; }
}
En este ejemplo, la interfaz IOrange
garantizaría que los implementadores al menos proporcionan una instancia de OrangePips
a sus herederos. Si el implementador lo quisiera, podrían expandir el alcance al public
completo:
public class NavelOrange : IOrange
{
public OrangePeel Peel { get { return new OrangePeel(); } }
protected OrangePips Seeds { get { return null; } }
}
public class ValenciaOrange : IOrange
{
public OrangePeel Peel { get { return new OrangePeel(); } }
public OrangePips Seeds { get { return new OrangePips(6); } }
}
La intención de protected
miembros protected
en las interfaces es proporcionar un contrato de soporte para herederos (subclases), por ejemplo:
public class SpecialNavelOrange : NavelOrange
{
...
// Having a seed value is useful to me.
OrangePips seeds = this.Seeds;
...
}
(Es cierto que esto no funcionaría para struct
s)
No puedo ver mucho de un caso de modificadores private
o internal
en las interfaces, pero el soporte de modificadores tanto public
como protected
parece perfectamente razonable.
Voy a tratar de explicar la utilidad de protected
miembros protected
en las interface
separándolos por completo de la interface
:
Imaginemos una nueva palabra clave C #, support
, para hacer cumplir los contratos heredadores, para que declaremos las cosas de la siguiente manera:
public support IOrangeSupport
{
OrangePips Seeds { get; }
}
Esto nos permitiría contratar clases para proporcionar miembros protegidos a sus herederos:
public class NavelOrange : IOrange, IOrangeSupport
{
public OrangePeel Peel { get { return new OrangePeel(); } }
protected OrangePips Seeds { get { return null; } }
}
Esto no es particularmente útil, porque las clases ya implicarían este contrato al proporcionar los miembros protected
en primer lugar.
Pero luego también podríamos hacer esto:
public interface IOrange : IOrangeSupport
{
...
}
De este modo, aplica IOrangeSupport
a todas las clases que implementan IOrange
y les exige que proporcionen miembros protected
particular, lo cual no es algo que podamos hacer actualmente.
Creo que todos abundaron en el objetivo de una interfaz que solo tenga miembros públicos, sin detalles de implementación. Lo que estás buscando es una clase abstracta .
public interface IOrange
{
OrangePeel Peel { get; }
}
public abstract class OrangeBase : IOrange
{
protected OrangeBase() {}
protected abstract OrangePips Seeds { get; }
public abstract OrangePeel Peel { get; }
}
public class NavelOrange : OrangeBase
{
public override OrangePeel Peel { get { return new OrangePeel(); } }
protected override OrangePips Seeds { get { return null; } }
}
public class ValenciaOrange : OrangeBase
{
public override OrangePeel Peel { get { return new OrangePeel(); } }
protected override OrangePips Seeds { get { return new OrangePips(6); } }
}
Editar: es justo argumentar que si tenemos un PlasticOrange que se deriva de un ornamento de clase, solo puede implementar IOrange y no el método protegido de Seeds. Eso está bien. Una interfaz por definición es un contrato entre un llamante y un objeto, no entre una clase y sus subclases. La clase abstracta es lo más cercano que llegamos a este concepto. Y eso está bien. Lo que esencialmente propones es otra construcción en el lenguaje a través del cual podemos cambiar las subclases de una clase base a otra sin romper la compilación. Para mí, esto no tiene sentido.
Si está creando una subclase de una clase, la subclase es una especialización de la clase base. Debe estar completamente al tanto de cualquier miembro protegido de la clase base. Pero si de repente desea cambiar la clase base, no tiene sentido que la subclase funcione con cualquier otro IOrange.
Supongo que tiene una pregunta justa, pero parece ser un caso de esquina y no veo ningún beneficio de eso para ser honesto.
Existen interfaces para permitir que las personas accedan a su clase sin saber cuál es la implementación concreta. Se divorcia por completo la implementación del contrato de transferencia de datos.
Por lo tanto, todo en una interfaz debe ser público. Los miembros no públicos solo son útiles si tiene acceso a la implementación y, por lo tanto, no contribuye significativamente a la definición de la interfaz.
Hay un buen juicio en el diseño actual de interfaces, que es que ofrece a los implementadores una mayor flexibilidad. Recuerde que muy a menudo las interfaces son escritas por programadores de framework y los implementadores son personas diferentes. Imponer la implementación sería innecesariamente duro.
Los miembros de la interfaz son una API pública; cosas como protected
etc. son detalles de implementación, y las interfaces no tienen ninguna implementación. Sospecho que lo que estás buscando es una implementación de interfaz explícita:
public class NavelOrange : IOrange
{
public OrangePeel Peel { get { return new OrangePeel(); } }
OrangePips IOrange.Seeds { get { return null; } }
}
No puedo ver por qué querría esto. Si desea que la clase derivada proporcione una implementación de un método particular, vaya a clases base abstractas. Las interfaces son solo eso: interfaces. Un contrato público, nada más. Piense en la interfaz a partir de la especificación que describe cómo debería verse la implementación en el mundo exterior. Una especificación para un enchufe de dos pines no establece (al menos asumo que) cómo debería ser su estructura interna. Solo debe ser compatible con la interfaz con un enchufe. Enchufe http://www.made-in-china.com/image/2f0j00MCetlafAYTWcM/Two-Round-pin-Plug-with-Power-Wire.jpg
Porque no tiene sentido. Una interfaz es un contrato expuesto públicamente. Soy un IThing, por lo tanto, realizaré los métodos IThing si me lo piden. No puedes pedirle a IThing que confirme que realiza métodos de los que no puede informarte.
Una interfaz contiene solo miembros públicos. Protegido significa que lo que sea que esté declarando solo está disponible para la clase y las instancias de clases derivadas.
Una interfaz es un contrato que promete cierta funcionalidad a los clientes. En otras palabras, el propósito de una interfaz es poder incluir un tipo en ella y pasarla de esa manera al código que necesita las características garantizadas por esa interfaz. Como el código de cliente de un tipo no puede acceder a miembros protegidos de ese tipo, no tiene sentido declarar elementos protegidos en una interfaz.
Una interfaz se trata de lo que un cierto objeto puede hacer, por lo que cuando se utiliza una clase que implementa esa interfaz, el desarrollador esperará que todos los miembros se implementen, por lo que el modificador de acceso protegido no significará nada para las interfaces.
Cualquier clase que implemente una interfaz .net tendrá que incluir implementaciones de todos los miembros de la interfaz. Además, cualquier clase puede exponer a una clase derivada los miembros que desee. Exigir que una implementación de una interfaz debe incluir un miembro que solo será utilizable a partir de clases derivadas no tendría ningún propósito útil, a menos que (1) dicho miembro sea visible para algo fuera de la interfaz o (2) las implementaciones de interfaz podrían usar miembros que ellos mismos no definieron. Si se permitiera que las interfaces incluyeran clases anidadas (que podrían acceder a los miembros protected
las interfaces), entonces protected
miembros de la interfaz protected
tendrían sentido. De hecho, podrían ser muy útiles si una clase anidada dentro de una interfaz pudiera definir métodos de extensión para esa interfaz. Desafortunadamente, no existe tal facilidad.
Por cierto, incluso sin poder anidar clases en interfaces, aún sería útil aplicar un modificador de acceso internal
a los miembros de la interfaz, con el efecto de que solo el ensamblaje donde se define la interfaz podría definir cualquier implementación para él.
Una interfaz es como la forma de una clave.
No es la llave.
No es la cerradura.
Es solo el delgado punto de contacto.
Por esta razón, todos los miembros de la interfaz (que define la forma de la clave) deben ser públicos.
Para que una tecla abra un candado, es importante que ambos compartan la misma forma.
Al hacer que la forma (la interfaz) sea pública , puede permitir que otros creen bloqueos compatibles o claves compatibles.
De lo contrario, al hacer que (la interfaz) sea interna , no permitirá que otros creen bloqueos compatibles o claves compatibles.