I\'m trying to override a property in a base class with a different, but derived type with the same name. I think its possible by covarience or generics but am not sure how
If SunData is assignment compatible with Outerspace Data (inherits from) then you don't need to modify the type of of OuterSpaceData
If you're looking for the covariance route, something like this should work:
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;
}
}
Fair warning, totally uncompiled code and I could be totally wrong :) But it's a stab at what I think you want...
Oh, and I think this is a .Net 4.0 only solution, I don't think you can do this earlier, co-variance was introduced there...
It is not possible the way you want it, exactly.
You can create a "new" property with the same name:
public new SunData Data
{
get { return (SunData) base.Data; }
set { base.Data = value; }
}
It's not quite the same thing, but it's probably as close as you're going to get.
Another possible approach would be:
public SunData SunData { get; set; }
public override OuterSpaceData Data
{
get { return SunData; }
set { SunData = (SunData)value; }
}
The advantage of this approach is that it does guarantee that it's impossible to put something in your Data property that is not a SunData. The downside is that your Data property is not strongly typed and you have to use the SunData property if you want it statically typed to SunData.
There's an ugly way to get the "best of both worlds" at the expense of being confusing to code and difficult to understand afterwards - by introducing an intermediate derived class that does a 'sealed override' on the base class Data property and redirects to a different protected property with a new name, and then have the ultimate derived class add a 'new' Data property that then calls the intermediate property. It really is an ugly hack, though, and even though I've done it, I wouldn't recommend it.
Not sure about Generics, but you could achieve a limited effect with simple Polymorphism (assuming SunData inherits from Data 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;
};
Try going about it with generics. The following class provides a generic base class for OuterSpace
with constraints on its parameters that enforce inheritance rules on the property types. I've omitted methods in the small types for clarity.
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 { }
The appeal of this approach is that it permits you to return strongly typed properties and enforce a basic inheritance constraint on the types of those properties. The methods are fully overridable; however, be advised that overriding may well be required to avoid casting issues with the base class implementation.