Reputation: 6157
I have 2 classes that are both derived from a base class X. The base class contains a property of a class T. Both subclasses of X should contain a property that's derived from T.
What I would like to achieve is to declare the a property of T in the base class X and have it used in several methods, while using the same property of T in the derived classes of X but have it recognized as a derived class from T, so that I won't have to cast it every time I want to use it.
One of my solutions would be just remove the property from the base class and copy the methods for each derived class of X, but that would defeat the purpose of using inheritance.
Is anything like that achievable?
internal class TestObject
{
public string ID;
public XObject obj;
//....
}
internal class TestDocument : TestObject
{
public XDocument obj; //<--- want to be able to call obj in my methods
//as if it were an XDocument type but relate to the obj property in the base class
//....
}
internal class XObject
{
//....
}
internal class XDocument : XObject
{
//....
}
Upvotes: 1
Views: 2197
Reputation: 13783
This is possible by using generics.
First, let me explain the example classes. Let's say these are your properties:
public class BaseHead {}
public class OrganicHead : BaseHead {}
public class CyborgHead : BaseHead {}
And you now want to implement these heads on your person classes:
public class BaseCreature {}
public class OrganicCreature : BaseCreature {}
public class CyborgCreature : BaseCreature {}
The solution:
public class BaseCreature<THead> where THead : BaseHead
{
public THead Head { get; set; }
public BaseCreature(THead head)
{
this.Head = head;
}
}
BaseCreature
genericTHead
type to only allow types that either are BaseHead
or are derived from BaseHead
However, we also want to ensure that the right creature (organic/cyborg) only uses the correct head (organic/cyborg). This can be done by deriving from a BaseCreature
with a specific generic type:
public class OrganicCreature : BaseCreature<OrganicHead>
{
public OrganicCreature(OrganicHead head) : base(head)
{
}
}
CyborgCreature
is analogous.
Suppose you wanted to make it possible that every creature can use every type of head. If that's what you want, then you need to keep the generic parameter generic:
public class OrganicCreature<THead> : BaseCreature<THead> where THead : BaseHead
{
public OrganicCreature(THead head) : base(head)
{
}
}
CyborgCreature
is analogous.
Upvotes: 1
Reputation: 37000
Generics should work for you:
class Base<T> where T: MyType
{
T MyProperty { get; set; }
public void DoSomething()
{
// do something with MyProperty
}
}
with MyType
being the base-class of the property within Base
.
Then in your derived class you can define the generic constraint, e.g.
class Derived : Base<DerivedType>
{
}
Now an instance of Derived
has the property MyProperty
of type DerivedType
instead of MyType
.
So in your case TestObject
should be similar to this:
internal class TestObject<T> where T: XObject
{
public string ID;
public T obj;
//....
}
internal class TestDocument : TestObject<XDocument>
{
// obj is here of type XDocument
}
Upvotes: 4
Reputation: 249676
The simplest way would be to make the base class generic, and constrain the generic parameter to be derived form a certain class:
class BaseProp { }
class DerivedPropA: BaseProp { }
class DerivedPropB : BaseProp { }
abstract class X<T>
where T: BaseProp
{
public T Value { get; set; }
public abstract void With(T value);
}
class A : X<DerivedPropA>
{
public override void With(DerivedPropA value)
{
this.Value = value;
}
}
class B : X<DerivedPropB>
{
public override void With(DerivedPropB value)
{
this.Value = value;
}
}
Upvotes: 1
Reputation: 20843
Make the type of the property a generic parameter of your base class:
class PropertyTypeBase { }
class PropertyTypeA : PropertyTypeBase { }
class Base<T> where T : PropertyTypeBase
{
public T Property { get; }
}
class Foo : Base<PropertyTypeA>
{
public Foo()
{
PropertyTypeBase x = Property;
PropertyTypeA a = Property;
}
}
Upvotes: 1