Reputation: 907
I am learning OOP and have a question about what is exactly happening with the code below.
I have the classic Dog
Animal
example going. Dog
inherits Animal
.
public class Animal
{
public string Name { get; set; }
public virtual string Speak()
{
return "Animal Speak";
}
public string Hungry()
{
return this.Speak();
}
}
public class Dog : Animal
{
public override string Speak()
{
return "Dog Speak";
}
public string Fetch()
{
return "Fetch";
}
}
Both questions are based on this assignment: Animal a = new Dog();
Animal
and set it to a Dog
reference. Is there a specific term for this? a.Hungry()
, the output is "Dog Speak." If the output is "Dog Speak", why can I not call a.Fetch()
? What is the term for what's happening here?Any help and further reading on the particular topic would be greatly appreciated.
Upvotes: 5
Views: 156
Reputation: 1870
If you Create an Animal with a Dog, you only create A Animal and Have only the Propertys of Animal. This has an Simply Reason. Just a Example:
public class Animal
{
public string Name { get; set; }
public virtual string Speak()
{
return "Animal Speak";
}
public string Hungry()
{
return this.Speak();
}
}
public class Dog : Animal
{
public override string Speak()
{
return "Dog Speak";
}
public string Fetch()
{
return "Fetch";
}
}
public class Cat: Animal
{
public override string Speak()
{
return "Cat Speak";
}
public string Fetch()
{
return "Fetch";
}
}
So if you now Crate a Insance like this:
Animal a = new Dog();
You know that your Animal can Speak and that he is Hungry, Nothing more thats all that you need to know, you can Call a.Speak()
and your Animal returns "Dog Speak"
buf if you now change a like this: a = new Cat()
you can call a.Speak()
too but it Return something else ... the same call but different returns. Of course if you are sure that the Animal is really a Dog you can cast it back to the Explicit implementation.
var d= new Dog();
if(a is Dog)
d = a as Dog;
d is now a real Dog and can everything that only a Dog can but you cant assign anymore d as a Cat. Becorse its a Dog and not an Animal
Upvotes: 0
Reputation: 32521
Animal
and set it to a dog
implicit cast is done virtual
and not using it.:
public class Animal
{
public string Name { get; set; }
public string Speak()
{
return "Animal Speak";
}
public string Hungry()
{
return this.Speak();
}
}
public class Dog : Animal
{
public new string Speak()
{
return "Dog Speak";
}
public string Fetch()
{
return "Fetch";
}
}
static void Main(string[] args)
{
Animal a = new Dog();
Console.WriteLine(a.Hungry()); //Animal Speak
Console.ReadLine();
}
Upvotes: 0
Reputation: 26078
Dog
inside an variable that will accept any Animal
. This is called Polymorphism (actually not quite see Servy's comment)Like so:
Dog dog = (Dog)a;
dog.Fetch();
Otherwise as far as the compiler knows it could be any animal, and not all animals have the method Fetch
. Also note the cast would throw an InvalidCastError
if it was not actually a Dog
object.
Upvotes: 2
Reputation: 45155
Animal a = new Dog();
Is upcasting. You are creating a Dog
object and assigning it to a variable of the parent class. This is allowed, but...
a.Fetch();
Won't work. Why, because Animal
doesn't have a method called Fetch
, and as far as the compiler knows, a
can be any Animal
. If you want to call Fetch
you will need to cast a
back to a Dog
Dog d = (Dog)a;
d.Fetch();
Note however, that this will cause an error if a
isn't a Dog
, so usually you check first:
if (a is Dog)
{
Dog d = (Dog)a;
d.Fetch();
}
When you call
a.Hungry();
This is allowed, because Animal
has a Hungry
method. The Hungry
method called Speak
, but since a
is a Dog
and not the base Animal
, it'll call the Dog.Speak
method (this, as Servy pointed out elsewhere, is true polymorphism - the idea the actual code executed when calling a particular method will be different depending on the actual type of the object).
Upvotes: 4
Reputation: 203812
Dog
as if it were an Animal
. (Thanks to Matt Burland for reminding me that this is the appropriate term.)Animal
, and as such you can only access members that the compiler knows an Animal
can access, i.e. Speak
and Hungry
. It doesn't know that the Animal
is a Dog
, so it can't call Fetch
. The variable would need to be of type Dog
for you to be able to call Fetch
on it.Upvotes: 5
Reputation: 31206
the word for that is polymorphism
because your animal just happened to be instantiated as a Dog
, and it will execute all of Dog
's methods. Both Animal
and Dog
have a Speak
method, and Dog
inherits Hungry
from Animal
.Dog
's speak
method overrides Animal's
, so that's what gets executed.
the reason why you can't write a.Fetch
is because the compiler doesn't know that at design time.
for example
Animal a;
if(console.ReadLine() == "Dog")
{
a = new Dog();
}
else
{
a = new Animal();
}
a.Fetch();
at this point when you call a.Fetch
you don't know whether or not a is a dog
Upvotes: 1
Reputation: 144206
a
is an Animal
reference and it points to a Dog
object. This is a form of polymorphism (subtype polymorphism).
You can't call a.Fetch
since a
has type Animal
and the Fetch
method is not defined in your Animal
class.
Upvotes: 2