variable tipos propiedades propiedad polimorfismo overridable oculta miembro method heredado ejemplos declarar c# inheritance override covariance

c# - tipos - super variable java



Anular una propiedad con un tipo derivado y el mismo nombre C# (5)

Intento anular una propiedad en una clase base con un tipo diferente pero derivado con el mismo nombre. Creo que es posible por covarience o genéricos, pero no estoy seguro de cómo hacerlo?

El siguiente código obtiene el error:

Error 1 ''Sun.Cache'': escriba debe ser ''OuterSpace.Cache'' para que coincida con el miembro anulado ''OuterSpace.Cache''

public class OuterSpace { public virtual OuterSpaceData Data {get; set;} public virtual OuterSpaceAnalysis Analysis {get; set;} public virtual OuterSpaceCache Cache {get; set;} public class OuterSpaceData { //Lots of basic Data Extraction routines eg public virtual GetData(); } public class OuterSpaceAnalysis { //Lots of Generic Analysis on Data routines eg public virtual GetMean(); } public class OuterSpaceCache { //Lots of Caches of Past Analysis Results: public Dictionary<AnalysisType, List<Result>> ResultCache; } } public class Sun : OuterSpace { public override SunData Data {get; set;} public override SunAnalysis Analysis {get; set;} public override SunCache Cache {get; set;} public SunData : OuterSpaceData { //Routines to specific get data from the sun eg public override GetData(); } public SunAnalysis : OuterSpaceAnalysis { //Routines specific to analyse the sun: eg public double ReadTemperature(); } public SunCache : OuterSpaceCache { //Any data cache''s specific to Sun''s Analysis public Dictionary<AnalysisType, List<Result>> TempCache; } } public class Moon : OuterSpace {} etc.

Para el resultado final, cuando abordo el Objeto "Datos" de Sun no quiero que haya dos Objetos de Datos (Heredado y Clase Base) pero cuando intento anular la propiedad requiere que las variables de Sun sean del mismo tipo que clase base P.ej:

Sun EarthSun = new Sun() EarthSun.Analyse() //The OuterSpace Analysis Saves results to Sun Cache: //Now try use the result: EarthSun.Cache[0]...

Muy similar a esto, pero con el tipo derivado en lugar de string-array: C # invalida las variables variables utilizadas por el método de clase base

Y esta respuesta no tenía mucho sentido para mí: cómo anular el miembro de la clase base después de la herencia en C ++

¿O quizás esto significa que simplemente no es posible? ¿Puedo anular con tipos derivados?

¡Ayuda! :) ¿Hay trabajo alrededor?


Intente hacerlo con genéricos. La siguiente clase proporciona una clase base genérica para OuterSpace con restricciones en sus parámetros que imponen reglas de herencia en los tipos de propiedad. He omitido los métodos en los pequeños para mayor claridad.

public class OuterSpace<TData, TAnalysis, TCache> where TData : OuterSpaceData where TAnalysis : OuterSpaceAnalysis where TCache : OuterSpaceCache { public virtual TData Data { get; set; } public virtual TAnalysis Analysis { get; set; } public virtual TCache Cache { get; set; } } public class OuterSpaceData { } public class OuterSpaceAnalysis { } public class OuterSpaceCache { } public class Sun : OuterSpace<SunData, SunAnalysis, SunCache> { public override SunData Data { get; set; } public override SunAnalysis Analysis { get; set; } public override SunCache Cache { get; set; } } public class SunData : OuterSpaceData { } public class SunAnalysis : OuterSpaceAnalysis { } public class SunCache : OuterSpaceCache { }

El atractivo de este enfoque es que le permite devolver propiedades fuertemente tipadas y aplicar una restricción de herencia básica en los tipos de esas propiedades. Los métodos son completamente reemplazables; sin embargo, tenga en cuenta que puede ser necesario reemplazarlo para evitar problemas de conversión con la implementación de la clase base.


No es posible de la manera que quieres, exactamente.

Puede crear una propiedad "nueva" con el mismo nombre:

public new SunData Data { get { return (SunData) base.Data; } set { base.Data = value; } }

No es exactamente lo mismo, pero es probable que sea lo más cerca que puedas llegar.

Otro posible enfoque sería:

public SunData SunData { get; set; } public override OuterSpaceData Data { get { return SunData; } set { SunData = (SunData)value; } }

La ventaja de este enfoque es que garantiza que es imposible poner algo en su propiedad de Datos que no sea un SunData. El inconveniente es que su propiedad de Datos no está fuertemente tipada y debe usar la propiedad SunData si quiere que esté tipeada estáticamente en SunData.

Hay una manera fea de obtener lo mejor de ambos mundos a expensas de ser confuso para codificar y difícil de entender después: al introducir una clase derivada intermedia que hace una ''anulación sellada'' en la propiedad de datos de la clase base y redirige a un diferentes propiedades protegidas con un nuevo nombre, y luego hacer que la clase derivada final agregue una propiedad de datos ''nueva'' que luego llama a la propiedad intermedia. Sin embargo, realmente es un hack feo, y aunque lo haya hecho, no lo recomendaría.


No estoy seguro acerca de los genéricos, pero podría lograr un efecto limitado con el polimorfismo simple (suponiendo que SunData hereda de los datos, etc.)

public class Sun : OuterSpace { void SomeInitializationMethod() { Data = new SunData(); Analysis = new SunAnalysis(); // etc } } // You could also make casting simpler with a generic method on the base public T GetData<T>() { if (Data is T) { return Data as T; } return null; };


Si SunData es compatible con la asignación de datos de espacio extra (hereda de), entonces no es necesario modificar el tipo de datos de OuterSpaceData


Si está buscando la ruta de covarianza, algo como esto debería funcionar:

public class OuterSpace<TCacheType> where TCacheType : OuterSpaceCache { public virtual OuterSpaceData Data {get; set;} public virtual OuterSpaceAnalysis Analysis {get; set;} public virtual TCacheType Cache {get; set;} public class OuterSpaceData { //Lots of basic Data Extraction routines eg public virtual GetData(); } public class OuterSpaceAnalysis { //Lots of Generic Analysis on Data routines eg public virtual GetMean(); } public class OuterSpaceCache { //Lots of Caches of Past Analysis Results: public Dictionary<AnalysisType, List<Result>> ResultCache; } } public class Sun : OuterSpace<SunCache> { public override SunData Data {get; set;} public override SunAnalysis Analysis {get; set;} public SunData : OuterSpaceData { //Routines to specific get data from the sun eg public override GetData(); } public SunAnalysis : OuterSpaceAnalysis { //Routines specific to analyse the sun: eg public double ReadTemperature(); } public SunCache : OuterSpaceCache { //Any data cache''s specific to Sun''s Analysis public Dictionary<AnalysisType, List<Result>> TempCache; } }

Advertencia justa, código totalmente sin compilar y podría estar totalmente equivocado :) Pero es una puñalada de lo que creo que quieres ...

Ah, y creo que esta es una solución .Net 4.0 solamente, no creo que puedas hacer esto antes, la co-varianza fue introducida allí ...