I understand what a virtual function is. But what I don't get is how do they work internally?
class Animal
{
virtual string Eat()
{
return #"Eat undefined";
}
}
class Human : Animal
{
override string Eat()
{
return #"Eat like a Human";
}
}
class Dog : Animal
{
new string Eat()
{
return #"Eat like a Dog";
}
}
static void Main()
{
Animal _animal = new Human();
Console.WriteLine(_animal.Eat());
_animal = new Dog();
Console.WriteLine(_animal.Eat());
}
Output for the above gives:
Eat like a Human
Eat undefined
In the above code _animal is of type Animal which references a Human object or Dog object.
What does this mean? I understand in the memory _animal contains an address which will point to Human or Dog object. How does it decide which function to invoke. In the first case I override and hence child's implementation is called, but in second case I use new and hence the parent's implementation is called. Can you please explain me what happens under the hood?
Thanks in advance
Nick
It works like this. Imagine the compiler rewrote your classes into this:
class VTable
{
public VTable(Func<Animal, string> eat)
{
this.AnimalEat = eat;
}
public readonly Func<Animal, string> AnimalEat;
}
class Animal
{
private static AnimalVTable = new VTable(Animal.AnimalEat);
private static string AnimalEat(Animal _this)
{
return "undefined";
}
public VTable VTable;
public static Animal CreateAnimal()
{
return new Animal()
{ VTable = AnimalVTable };
}
}
class Human : Animal
{
private static HumanVTable = new VTable(Human.HumanEat);
private static string HumanEat(Animal _this)
{
return "human";
}
public static Human CreateHuman()
{
return new Human()
{ VTable = HumanVTable };
}
}
class Dog : Animal
{
public static string DogEat(Dog _this) { return "dog"; }
public static Dog CreateDog()
{
return new Dog()
{ VTable = AnimalVTable } ;
}
}
Now consider these calls:
Animal animal;
Dog dog;
animal = new Human();
animal.Eat();
animal = new Animal();
animal.Eat();
dog = new Dog();
dog.Eat();
animal = dog;
animal.Eat();
The compiler reasons as follows: If the type of the receiver is Animal then the call to Eat must be to animal.VTable.AnimalEat. If the type of the receiver is Dog then the call must be to DogEat. So the compiler writes these as:
Animal animal;
Dog dog;
animal = Human.CreateHuman(); // sets the VTable field to HumanVTable
animal.VTable.AnimalEat(animal); // calls HumanVTable.AnimalEat
animal = Animal.CreateAnimal(); // sets the VTable field to AnimalVTable
animal.VTable.AnimalEat(animal); // calls AnimalVTable.AnimalEat
dog = Dog.CreateDog(); // sets the VTable field to AnimalVTable
Dog.DogEat(dog); // calls DogEat, obviously
animal = dog;
animal.VTable.AnimalEat(animal); // calls AnimalVTable.AnimalEat
That is exactly how it works. The compiler generates vtables for you behind the scenes, and decides at compile time whether to call through the vtable or not based on the rules of overload resolution.
The vtables are set up by the memory allocator when the object is created. (My sketch is a lie in this regard, since the vtable is set up before the ctor is called, not after.)
The "this" of a virtual method is actually secretly passed as an invisible formal parameter to the method.
Make sense?
I understand in the memory _animal contains an address which will point to Human or Dog object. How does it decide which function to invoke.
Like data, code also has an address.
Therefore the typical approach to this problem is for Human or Dog objects to contain the address of the code of their methods. This is sometimes called using a vtable. In a language like C or C++ this concept is also directly exposed as what's called a function pointer.
Now, you've mentioned C#, which has a pretty high-level type system, in which types of objects are also discernible at runtime.... Therefore the implementation details may differ from the traditional approach in some way. But, as to your question, the function pointer/v-table concept is one way to do it, and it would surprise me if .NET has strayed too much from this.
In C#, derived classes must provide the override modifier for any overridden method inherited from a base class.
Animal _animal = new Human();
It's not just the Human object got constructed. They are two sub-objects. One is Animal sub-object and the other is Human sub-object.
Console.WriteLine(_animal.Eat());
When made the call to _animal.Eat();, the run time checks whether the base class method ( i.e., Eat() )is overridden in the derived class. Since, it is overridden, the corresponding derived class method is called. Hence the output -
Eat like a Human
But, in case of -
_animal = new Dog();
Console.WriteLine(_animal.Eat());
In the Dog, there is no Eat() overridden method in the derived class Dog. So, base class method itself is called. Also this method of checking is done because in the base class, Eat() is mentioned as virtual and calling mechanism is decided at run-time. To sum up, virtual calling mechanism is a run-time mechanism.
Related
Let's say that i have a base class Animal.
public abstract class Animal;
This animal class has the abstract method:
public abstract T Copy<T>() where T : Animal
When this method is overridden in the Lion class:
public class Lion : Animal
{
string roar = "Roar";
}
i wish to return a copy of this lion without its references. So what i think it should be overridden like is this:
public abstract T Copy<T>()
{
return new Lion(){
roar = this.roar;
}
}
but this is not allowed, because Lion cannot be converted to the T type(which is an Animal).
This is a understandable error, becouse not every Animal is necessarily a Lion.
But how can i set this situation up where the copy method knows it supposed to return the subclass, Lion in this case, and not have to do all kinds of casting to the correct type? And still have every animal have a method Copy().
You don't need to use a generic method in this case, because every Lion is an Animal, so you can simply make Copy return an Animal
public abstract class Animal
{
public abstract Animal Copy();
}
public class Lion : Animal
{
public string Roar {get; set;} = "Roar";
public override Animal Copy()
{
return new Lion
{
Roar = this.Roar
};
}
}
Then testing it like so:
public static void Main()
{
var lion1 = new Lion();
var lion2 = lion1.Copy();
Console.WriteLine(lion1 == lion2);
}
Prints false to the console, as expected because C# classes are reference types and the default == implementation checks for reference equals on classes and our two lions aren't the same object in memory.
Now every subclass of Animal must implement the method Copy returning an Animal. Which animal that is doesn't matter
You can not use generics in this situation, they don't support what you want to do.
However, if you're on C# 9 you can use the new "Covariant return types" support.
Specifically, you can write your code like this:
public abstract class Animal
{
public abstract Animal Copy();
}
public class Lion : Animal
{
public override Lion Copy() => new Lion();
// ^
// notice that I used Lion here, not Animal
}
If you're calling Copy through a reference declared as being of type Animal but referencing an instance of Lion, you will get back a value typed to Animal, holding a Lion reference.
However, if you're calling Copy through a reference typed to Lion, you will get back a reference typed to Lion as well.
Example:
Animal a = new Lion();
Animal c = a.Copy(); <-- holding a Lion, but type is Animal
Lion l = new Lion();
Lion l2 = l.Copy(); <-- type is now Lion as well
If you're not on C# 9, a different option would be to make the Copy method know the type of the derived class, by making Animal generic:
void Main()
{
Animal<Lion> a = new Lion();
Lion c1 = a.Copy(); // <-- notice that this is now typed to Lion as well
Lion l = new Lion();
Lion c2 = l.Copy();
}
public abstract class Animal<T> where T : Animal<T>
{
public abstract T Copy();
}
public class Lion : Animal<Lion>
{
public override Lion Copy() => new Lion();
}
This, however, means you always have to declare Animal as the right type of animal so you lose some of the benefits of having this base class.
There is a behavior in C# I really do not understand:
class Animal {
public string species = "animal";
public void Introduce() {
Console.WriteLine(species);
}
}
class Cat: Animal {
new public string species = "cat";
// public void Introduce() {Console.WriteLine(species);}
}
class Program
{
static void Main(string[] args)
{
var cat = new Cat();
cat.Introduce();
}
}
This piece of code, when executed, outputs >>> animal.
For me, since Cat inherits Animal, calling cat.Introduce should call Animal.Introduce "in the scope of the cat instance". ie I don't understand why the program picks the species field of Animal and not the one of Cat...
I know I could use workarounds, but I believe I'm missing some point about c# design, can someone explain this behavior?
Thanks
I don't understand why the program picks the species field of Animal and not the one of Cat...
Because the new modifier hides the inherited species member... but only inside the Cat instance. You call the method on the base class, which only knows its own species member.
If you give your Cat class an IntroduceCat() method where you print its species and you call it, you'll see the "cat" string being printed.
If you want to override the member in a derived class, you must mark the member as virtual in the base class and override it in the derived class. But you can't do that to fields, so you'll have to make it a property.
But you probably just want to assign a different value, and you can do so in your constructor.
Given
public class Animal
{
public Animal()
{
Console.WriteLine("Animal constructor called");
}
public virtual void Speak()
{
Console.WriteLine("animal speaks");
}
}
public class Dog: Animal
{
public Dog()
{
Console.WriteLine("Dog constructor called");
this.Speak();
}
public override void Speak()
{
Console.WriteLine("dog speaks");
base.Speak();
}
}
this.Speak() calls Dog.Speak(). Remove Speak() from dog and suddenly this.Speak() calls Animal.Speak(). Why does this behave this way? In other words, why does this mean base or this?
To me, an explicit call to base.Speak() makes more sense. Especially when speak is not virtual, surprisingly Speak() is still called when virtual is removed. I understand IS-A relationships from an OO sense, but I can't wrap my head around this specific problem in C#. This gets especially annoying when people write God class UI's (practically every business does). I'm looking for "Speak()" inside "this" when I should be looking at "base".
Subclases automatically inherit behavior from their base classes. If you don't do anything other than inherit Dog from Animal then this.Speak() and base.Speak() both reference the version of Speak() that was implemented in Animal.
Where special things start happening is if Dog overrides Speak(). This is not possible unless Speak() is virtual. (The virtual keyword doesn't control inheritance, it controlls overriding.)
Only when Dog overrides Speak() does base.Speak() do something special: In that case, calling Speak() (or this.Speak()) will execute Dog's implementation, because it overrides Animal's implementation. This is where base becomes useful: it allows you to get around this behavior by specifying that you want to execute the base class's implementation rather than the override.
A common use of this style is in constructors. For example:
public class Animal
{
private readonly string _name;
public Animal() : this("Animal") { }
protected Animal(string name) { _name = name; }
public void Speak() { Console.WriteLine(_name + " speaks"); }
}
public class NamedAnimal : Animal
{
public NamedAnimal(name) : base(name) { }
}
// usage:
(new Animal()).Speak(); // prints "Animal speaks"
(new NamedAnimal("Dog")).Speak(); // prints "Dog speaks"
In this example, NamedAnimal doesn't have access to the _name field, but it is still able to set it indirectly by calling the base class's constructor. But the base class's signature is the same as one in the base class, so it has to be specified using base.
With non-constructors it's also useful to get at behavior that's not otherwise accessible. For example, if Animal.Speak were virtual then we could use an override to tack behavior onto it rather than simply replacing it:
public class NamedAnimal : Animal
{
public NamedAnimal(name) : base(name) { }
public override Speak()
{
Console.Write("The animal named ");
base.Speak();
}
}
// usage:
(new NamedAnimal("Dog")).Speak(); // Writes "The animal named Dog speaks"
Its not that. Its that if there is a speak method within dog, then it is an override of the base method. If it isn't there, then calling dogInstance.Speak will look for the Speak() method in any of Dog's base classes.
This is one of the very fundamental points of OO. If you don't provide an override, then the parent method is used.
Also, even if you remove virtual, Dog.Speak is called because you're not accessing this polymorphically.
this means this and nothing else.
Just in your first example you have an override for Speak(..) function, so this call that one.
In second case, istead, there is no any override, so it "climbs" on derivation tree and pick the first suitable function. In your case that one is Speak(..) of the Animal.
VB.Net has the MyClass keyword to do just that (as opposed to the My keyword, which is the equivalent of this in C#). Unfortunately, there is no MyClass equivalent keyword in C#.
Got a task to make a program that registers animals and the object is to get familiar with inheritance, polymorphism and so on.
One thing that pussles me is no matter how much I read about it just seems pointless.
I create my main class which is animal with some generic fields that apply to all animals lets say name, age and species.
So far so good all animals has this info but every animal has a unique field aswell so ill create my cat as public class cat : animal and give the cat the field teeth for example.
Now I want to make a new animal which is a cat, im taking data from several listboxes so I would need a constructor that takes those parameters and this is what I dont get, do I have to declare them in every child class aswell?
I know that my animal should have 3 parameters from the animal class plus another from the cat class so the new cat should accept (name, age, species, teeth) but it seems that I have to tell the constructor in the cat class to accept all of these and theres my question, what purpose does the animal class serve? If I still need to write the code in all subclasses why have the base class? Probably me not getting it but the more I read the more confused I become.
Like Sergey said, its not only about constructors. It saves you having to initialize the same fields over and over. For example,
Without inheritance
class Cat
{
float height;
float weight;
float energy;
string breed;
int somethingSpecificToCat;
public Cat()
{
//your constructor. initialize all fields
}
public Eat()
{
energy++;
weight++;
}
public Attack()
{
energy--;
weight--;
}
}
class Dog
{
float height;
float weight;
float energy;
string breed;
int somethingSpecificToDog;
public Dog()
{
//your constructor. initialize all fields
}
public Eat()
{
energy++;
weight++;
}
public Attack()
{
energy--;
weight--;
}
}
With Inheritance
Everything common to animals gets moved to the base class. This way, when you want to setup a new animal, you don't need to type it all out again.
abstract class Animal
{
float height;
float weight;
float energy;
string breed;
public Eat()
{
energy++;
weight++;
}
public Attack()
{
energy--;
weight--;
}
}
class Cat : Animal
{
int somethingSpecificToCat;
public Cat()
{
//your constructor. initialize all fields
}
}
class Dog : Animal
{
int somethingSpecificToDog;
public Dog()
{
//your constructor. initialize all fields
}
}
Another advantage is, if you want to tag every animal with a unique ID, you don't need to include that in each constructor and keep a global variable of the last ID used. You can easily do that in the Animal constructor since it will be invoked everytime the a derived class is instantiated.
Example
abstract class Animal
{
static int sID = 0;
float height;
float weight;
int id;
public Animal()
{
id = ++sID;
}
}
Now when you do;
Dog lassie = new Dog(); //gets ID = 1
Cat garfield = new Cat(); // gets ID = 2
If you want a list of all Animals in your 'farm',
without inheritance
List<Cat> cats = new List<Cat>(); //list of all cats
List<Dog> dogs = new List<Dog>(); //list of all dogs
...etc
With inheritance
List<Animal> animals = new List<Animal>(); //maintain a single list with all animals
animals.Add(lassie as Animal);
animals.Add(garfield as Animal);
This way, if you want to see if you have an animal called Pluto, you just need to iterate over a single list (animals) rather than multiple lists (Cats, Dogs, Pigs etc.)
EDIT in response to your comment
You don't need to instantiate Animal. You simply create an object of whichever Animal you want to. In fact, since an Animal will never be a generic Animal, you can create Animal as an abstract class.
abstract class Animal
{
float height;
float weight;
float energy;
string breed;
public Eat()
{
energy++;
weight++;
}
public Attack()
{
energy--;
weight--;
}
}
class Cat : Animal
{
int somethingSpecificToCat;
public Cat()
{
//your constructor. initialize all fields
}
}
class Dog : Animal
{
int somethingSpecificToDog;
public Dog()
{
//your constructor. initialize all fields
}
}
Cat garfield = new Cat();
garfield.height = 24.5;
garfield.weight = 999; //he's a fat cat
//as you can see, you just instantiate the object garfield
//and instantly have access to all members of Animal
Animal jerry = new Animal(); //throws error
//you cannot create an object of type Animal
//since Animal is an abstract class. In this example
//the right way would be to create a class Mouse deriving from animal and then doing
Mouse jerry = new Mouse();
Edit to your comment
If you store it in a list of Animals, you still have access to all fields. You just have to cast it back to its original type.
List<Animal> animals = new List<Animal>();
animals.Add(garfield as Animal);
animals.Add(lassie as Animal);
//if you do not cast, you cannot access fields that were specific to the derived class.
Console.WriteLine(animals[0].height); //this is valid. Prints Garfield's height
Console.WriteLine(animals[0].somethingSpecificToCat); //invalid since you haven't casted
Console.WriteLine((animals[0] as Cat).somethingSpecificToCat); //now it is valid
//if you want to do it in a loop
foreach(Animal animal in animals)
{
//GetType() returns the derived class that the particular animal was casted FROM earlier
if(animal is Cat)
{
//the animal is a cat
Cat garfield = animal as Cat;
garfield.height;
garfield.somethingSpecificToCat;
}
else if (animal is Dog)
{
//animal is a dog
Dog lassie = animal as Dog;
lassie.height;
lassie.somethingSpecificToDog;
}
}
You probably need to bare in mind that the example you are working through is extremely simple. If you need some complex method to determine one of the base class values you wouldn't want to be writing/replicating this in multiple classes as this would become tedious and make maintenance of the code a nightmare, in these types of situations the declaration of a few params in a constructor becomes trivial.
The benefit is that you dont have to declare the name age species in every type of animal. You get them pre-made for you. Another great point that inheritance lets you do is. Lets say you want to have an array of animals. So you type something like . Arraylist arr = etc etc...
but this will only hold cat type objects. So instead you can do something like Arraylist and this will hold all types of animals, cats and dogs. Basically a variable of a base class can point to a variable of a derived class. This comes real handy in most scenarios, as things get complicated.
You need to tell the contructor to take the arguments (if you wan't to require them), but you do not need to implement the properties again:
public class Animal
{
public string Name { get; set; }
public Animal(string Name)
{
Name = name;
}
}
public class Cat : Animal
{
public int Teeth { get; set; }
public Cat(string name, int teeth)
{
Name = name; //<-- got from base
Teeth = teeth; //<-- defined localy
}
//or do this
public Cat(string name, int teeth) : base(name)
{
Teeth = teeth;
}
}
You can also do the following:
Cat cat = new Cat("cat", 12);
Animal kitty = cat as Animal;
Which makes sense e.g. if you want a list like List<Animal> you can add a Cat-instance:
List<Animal> animals = new List<Animal>();
animals.Add(new Animal("Coco"));
animals.Add(cat);
foreach(Animal animal in animals)
{
Console.WriteLine(String.Format("Name: {0}", animal.Name));
if(animal is Cat)
{
Console.WriteLine(String.Format("{0} is a Cat with {1} teeth.", animal.Name
(animal as Cat).Teeth));
}
Console.WriteLine("============");
}
which will output:
Name: Coco
============
Name: cat
cat is a Cat with 12 teeth.
============
Inheritance is not about constructors only. For example, in your base class Animal you can declare method Eat(something) or Grow() which will be equal for all the successors.
BTW, no problem is in calling default Cat() constructor with just three parameters (so calling the base Animal constructor) and then specifying teeth by setting appropriate field or property.
I don't know if the following information will be of any use for you but I thought it'd be worth mentioning as a use of inheritance.
One of the many uses of inheritance, or to be more specific, a super class is that you can put them in the same collection:
List<Animal> animals = new List<Animal>();
animals.Add(new Cat());
animals.Add(new Dog());
etc. etc.
Don't forget you can just pass constructor params to the base contructor too. You don't have to init them all in every derived class.
eg (stealing chrfin's code):
public class Animal
{
public string Name { get; set; }
}
public class Cat : Animal
{
public int Teeth { get; set; }
public Cat(string name, int teeth) : Base(name) //pass name to base constructor
{
Teeth = teeth;
}
}
You're totally overthinking this.
what purpose does the animal class serve?
Your scenario is really, really simple. Try to think of it this way: the more common the feature is, the higher in the hierarchy it should be placed. Why? Simply to avoid duplication and redundancy. Imagine having few additional classes: dog, horse and frog. Since cat, dog and horse are mammals, you could as well create a class mammal defining shared mammals' features. Why? For example to avoid writing the same constructors, fields, methods for the similar species. In your case try to think of your animal class as of a repository of features common to all animals.
Yes you will have to create the constructors, but that doesn't make inheritance pointless, although it is actually a good design practice to prefer composition over inheritance, that is generally (not always) it is better to have a cat that HAS-A animal property than a cat that IS-A animal.
Going back to inheritance, when it really pays off, since there are some attributes that all your animals will have think maybe, legs, ears, head, and by using inheritance you will not have to declare those properties in every class you create.
Also with inheritance you can use polymorphism, say you have this class (pseudo-code)
public abstract class Animal()
{
//Some atributes
//Methods
makeSound();
}
then you have
public class Cat extends Animal
{
makeSound()
{
System.out.println("meow");
}
}
Then say you extend Animal for dog also:
public class Dog extends Animal
{
makeSound()
{
System.out.println("woof")
}
}
Now say you have an array declared like this:
List<Animal> animals = new ArrayList<Animal>();
animals.add(cat);
animals.add(dog);
Then say you want each animal to make his sound then you can use polymorphism, and that will make each implementation call its makeSound method:
for (Animals animal : animals)
{
animal.makeSound();
}
And that will print for the cat
"meow"
and for the dog
"woof"
Inheritance allows you to write code that is shared between classes so that you put common functionality/data within a base class and have other classes derive from it. To use your example:
class Animal
{
public string Name { get; set; }
public Animal(string name)
{
Name = name;
}
}
class Cat : Animal
{
// Put cat-only properties here...
public Cat(string name) : base(name)
{
// Set cat-specific properties here...
}
}
You don't even need to supply the same amount of parameters to each class constructor - if a cat doesn't have a name (for a contrived example) just create a Cat constructor with no parameters and pass in something suitable to the base constructor. This allows you to control how all the animal classes are setup.
You are getting confused because you are thinking only about constructors. The fact is as explained in msdn, "Constructors and Destructors are not inherited". So when you inherit you a class the base class constructors do not apply to derived class. Derived class has to mention its own set of construtor/destructor. To understand why this is so you might look here: Why are constructors not inherited?.
Now coming to your question, Yes you have to add a constructor in your cat class to accept all the four parameters. But you need not have to implement those 3 fields again in your cat class. All public protected and internal fields and methods of your animal class are still available to your cat class and you do not have to reimplement them in your derived class. This is how your base class is serving your derived class.
I want something like this:
public interface IAnimal
{ }
public class Dog : IAnimal
{
public Dog() {}
}
public class Cat : IAnimal
{
public Cat() {}
}
public abstract class TestClassBase
{
public TestClassBase()
{
_lazyAnimal = CreateLazyAnimal();
}
private Lazy<IAnimal> _lazyAnimal = null;
public IAnimal Animal
{
get
{
IAnimal animal = null;
if (_lazyAnimal != null)
animal = _lazyAnimal.Value;
return animal;
}
}
// Could be overridden to support other animals
public virtual Lazy<IAnimal> CreateLazyAnimal()
{
// default animal is a dog
return new Lazy<Dog>(); // this type of casting doesn't work and I don't know a good workground
}
}
I know from tinkering with MEF that it manages to find and store different types, implementing a single interface, into Lazy<T>. Just not sure how to do it myself.
Lazy<Dog> cannot be converted directly to Lazy<IAnimal>, but since Dog can be converted to IAnimal you can use the Lazy<IAnimal> constructor overload that expects an IAnimal (strictly speaking, it takes a Func that returns an IAnimal) and provide a Dog instead:
public virtual Lazy<IAnimal> CreateLazyAnimal()
{
// default animal is a dog
return new Lazy<IAnimal>(() => new Dog());
}
Casting Lazy<Dog> to Lazy<IAnimal> is not allowed because the types are different (the Lazy<T> type inherits just from object). In some cases, the casting can make sense - for example casting IEnuerable<Dog> to IEnumerable<IAnimal>, but the casting isn't safe in all cases.
C# 4.0 adds support for this casting in the safe case. It is called covariance and contravariance. For example, this article gives a nice overview.
Unfortunatelly, in C# 4.0 this works only for interfaces and delegates and not for concrete classes (e.g. Lazy<T>). You could probably solve the problem by creating interface ILazy<out T> and a wrapper for standard Lazy type, but it is probably easier to just write conversion from Lazy<Dog> to Lazy<IAnimal>.