A simplified example of what i'm trying to achieve looks like this:
public class Animal
{
public virtual Teeth teeth {get;set;}
}
public class Mouse : Animal
{
public override SmallTeeth teeth {get; set;} // SmallTeeth Inherits from Teeth
}
This obviously doesn't work as teeth must be same type as in the Animal class to be overriden in the Mouse class. But can something like this be achieved where I would be allowed to use the more derived type in any functions that are inherited from Animal? For example if the Animal class contained a function to bite:
public void Bite()
{
teeth.bite()
Console.WriteLine("Ouch")
}
I could call the Bite()
function inherited from Animal and it would use the Mouse class' field of type SmallTeeth
. Is this possible? and is it the best way to do what i'm trying to do? If not, what would be the correct approach to this problem?
Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass.
Overriding Properties in C# We can also override the property of a parent class from its child class similar to a method. Like methods, we need to use virtual keyword with the property in the parent class and override keyword with the porperty in the child class.
In Java inheritance we can access parent class properties via the child class object, as there is a keyword extends for achieving inheritance.
An overriding property declaration must specify exactly the same access modifier, type, and name as the inherited property. Beginning with C# 9.0, read-only overriding properties support covariant return types. The overridden property must be virtual , abstract , or override .
NOTE: This answer was written in 2016. Return type covariance has (amazingly!) been added to C# in the years since. Keep that in mind when reading this answer.
The feature you want is called return type covariance, and C# does not support it. (C++ does, incidentally.)
The usual case made for covariant return types is:
abstract class Animal
{
public abstract Cage GetCage();
}
public class Fish : Animal
{
public override Aquarium GetCage() { ... }
}
This is not legal, but if it were legal it would be safe. That is, if you have an Animal in hand and you ask for a cage, you get one, even if it is a fish. Why? Because an aquarium is a kind of cage.
What you propose though is not only illegal, it's unsafe:
Animal animal = new Mouse();
animal.Teeth = new TRexTeeth();
The contract is that the setter can be called with any kind of tooth. By making the derived class more restrictive in what it can accept, you violate the contract of the base class.
So don't do that.
There are a bunch of ways though that you can achieve what you want in C#.
Here's just one of them:
interface IAnimal
{
Teeth Teeth { get; } // READ ONLY
}
class Mouse : IAnimal
{
private SmallTeeth smallTeeth;
public SmallTeeth Teeth
{
get { return smallTeeth; }
}
Teeth IAnimal.Teeth { get { return this.Teeth; } }
}
Now if you cast a mouse to IAnimal you get the property that returns Teeth, and if you use a mouse normally you get the property that returns SmallTeeth.
I describe another way to solve this problem here:
Does C# support return type covariance?
And the generic solution given in the other answer also works, though personally I prefer to keep generics out of it unless necessary.
Do a search on "return type covariance in C#" for more information on this pattern.
Actually yes. You could but should not use generics
for that purpose including a type constraint (see comments below and the post of Eric Lippert who explains in detail, what you are wanting or trying to achieve in your situation):
public class Animal<T> where T : Teeth
{
public virtual T teeth {get;set;}
}
public class Mouse : Animal<SmallTeeth>
{
public override SmallTeeth teeth {get; set;} // SmallTeeth Inherits from Teeth
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With