polimorfismo polimorfico parametrico metodos herencia form and abstractos c# inheritance

polimorfico - ¿Cómo devolver subtipo en el método reemplazado de la subclase en C#?



polimorfismo parametrico c# (7)

Tengo una subclase con un método omitido que sé que siempre devuelve un subtipo particular del tipo de devolución declarado en la clase base. Si escribo el código de esta manera, no se compilará. Como eso probablemente no tiene sentido, déjame dar un ejemplo de código:

class BaseReturnType { } class DerivedReturnType : BaseReturnType { } abstract class BaseClass { public abstract BaseReturnType PolymorphicMethod(); } class DerivedClass : BaseClass { // Compile Error: return type must be ''BaseReturnType'' to match // overridden member ''BaseClass.PolymorphicMethod()'' public override DerivedReturnType PolymorphicMethod() { return new DerivedReturnType(); } }

¿Hay alguna forma de lograr esto en C #? Si no, ¿cuál es la mejor manera de lograr algo similar? ¿Y por qué no está permitido? No parece permitir ninguna incoherencia lógica, ya que cualquier objeto devuelto por el método over- is BaseReturnType todavía is BaseReturnType . Tal vez hay algo que no había considerado sin embargo. O tal vez la razón sea tecnológica o histórica.


Cambia la firma de tu método en la clase Derivada a:

public override BaseReturnType PolymorphicMethod() { return new DerivedReturnType(); }

C # no admite tipos de devolución de variantes. Puede consultar esta publicación para obtener información sobre cómo usar Genéricos ... http://srtsolutions.com/blogs/billwagner/archive/2005/06/17/covaraint-return-types-in-c.aspx

Aquí hay una muestra usando Generics en su modelo:

public class BaseReturnType { } public class DerivedReturnType : BaseReturnType { } public abstract class BaseClass<T> where T : BaseReturnType { public abstract T PolymorphicMethod(); } public class DerviedClass : BaseClass<DerivedReturnType> { public override DerivedReturnType PolymorphicMethod() { throw new NotImplementedException(); } }


Lamentablemente, no, los tipos de retorno covariantes no se admiten en C # para anulación de método. (Ídem tipos de parámetros contravariantes)

Si está implementando una interfaz, puede implementarla explícitamente con la versión "débil" y también proporcionar una versión pública con el contrato más sólido. Para una anulación simple de una clase para padres, no tengo este lujo, me temo :(

(EDIT: Marc tiene una solución razonable , aunque es bastante feo, y el método de ocultarse es generalmente algo malo para la legibilidad. Sin ofender, Marc;)

Creo que esto es realmente una restricción de CLR, no solo una de idioma, pero podría estar equivocado.

(Como cuestión de historia, Java (el lenguaje) tenía la misma restricción hasta 1.5, pero ganó covarianza al mismo tiempo que los genéricos).


Los genéricos no son necesariamente el camino a seguir. En particular, el tipo (de derivado) no se considera un tipo (de base).

Primero, agregue un nuevo método a su clase derivada que devolverá el valor con el tipo correcto. En segundo lugar, marque el método de anulación no invalidable y haga que delegue en su nuevo método.

Eso es. Has resuelto tu problema Las clases secundarias no podrán volver a expandir el tipo porque deben anular su nuevo método.

Me disculpo si el código no es del todo correcto; Estoy acostumbrado a VB.net.

abstract class C1 { public abstract IEnumerable<Byte> F1(); } class C2 : C1 { public sealed override IEnumerable<Byte> F1() { Return F2(); } public overridable IList<Byte> F2() { Return {1, 2, 3, 4}; } }


Me parece que debe devolver una interfaz, no una clase base.


Puede hacer esto si introduce un método adicional para anular (ya que no puede override y new un método con el mismo nombre en el mismo tipo):

abstract class BaseClass { public BaseReturnType PolymorphicMethod() { return PolymorphicMethodCore();} protected abstract BaseReturnType PolymorphicMethodCore(); } class DerivedClass : BaseClass { protected override BaseReturnType PolymorphicMethodCore() { return PolymorphicMethod(); } public new DerivedReturnType PolymorphicMethod() { return new DerivedReturnType(); } }

Ahora tiene un método PolymorphicMethod en cada nivel con el tipo correcto.


Puedes hacer que la clase sea genérica si eso no te molesta:

class BaseReturnType { } class DerivedReturnType : BaseReturnType { } abstract class BaseClass<T> where T : BaseReturnType { public abstract T PolymorphicMethod(); } class DerivedClass : BaseClass<DerivedReturnType> { // Error: return type must be ''BaseReturnType'' to match // overridden member ''BaseClass.PolymorphicMethod()'' public override DerivedReturnType PolymorphicMethod() { return new DerivedReturnType(); } }


class BaseReturnType { } class DerivedReturnType : BaseReturnType { } abstract class BaseClass { public abstract BaseReturnType PolymorphicMethod(); } class DerivedClass : BaseClass { // Error: return type must be ''BaseReturnType'' to match // overridden member ''BaseClass.PolymorphicMethod()'' public override BaseReturnType PolymorphicMethod() { return new DerivedReturnType(); } }

Esto debería funcionar