i have these 2 classes
class Animal
{
public string name;
public virtual void MakeSound()
{
Console.WriteLine("some sound");
}
}
class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("bark");
}
}
id like to know where the differences are between these 2 objects?
Animal dog = new Dog();
Dog dog2 = new Dog();
edit: my problem with this is that i do not understand the process/ thought behind these 2 object. Yes, they both are Dog() object, but what I do not understand WHY i have the possibility to assign Animal AND Dog to the type. I get that "assign" is the wrong wording but what it just seems VERY weird to me that I have the possibility to do that.
Programming has treated me "harshly" until now. Everything has to have the right syntax and everything has to be in the right order and everything hast to make sense. If thats not the case i get an error
List<int> list = new List<int>; doesn't work, neither does List<int> list = new List(); nor something else. Thats why I don't get the 2 objects. It seems to me that, functionality wise, they both do and can do the same. But are they actually the same?
As the Animal class is more generic, you can use only for declaration, for instance if you don't know yet what animal is, and change to another subclass as you need. Imagine you have also:
class Cat: Animal
{
public override void MakeSound()
{
Console.WriteLine("mew");
}
}
You could do:
Animal animal = new Dog();
Dog dog2 = new Dog();
animal.MakeSound();
animal = new Cat();
animal.MakeSound();
And the output is:
bark
mew
If you only use the Dog class, you have to create another variable for Cat.
I hope this help you.
EDIT
The power can be seen when you make a list or dictionary (or other collection) containing different animals:
var animals = new List<Animal>();
animals.Add(new Dog("Rover"));
animals.Add(new Cat("Tiger"));
foreach (var animal in animals)
{
Console.WriteLine($"{animal.name} goes:");
animal.MakeSound();
}
Output:
Rover goes:
bark
Tiger goes:
mew
There is no big difference.
The only real difference is that if you would implement a public method or property in the Dog class which is not in the Animal class, you would not be able to access them unless you cast it like ((Dog)dog).SomeProperty.
Probably the only time you use the Animal class instead of the Dog class is if you need a List containing all the animals.
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.
I'm trying to create generic method to filter results from several method returning lists of types that are deriving from same base type. I prepared a simplified version of my problem:
using System;
using System.Collections.Generic;
using System.Linq;
public class Animal
{
public string Name { get; set; }
}
public class Cat : Animal { }
public class Dog : Animal { }
public class Program
{
public static void Main()
{
Console.WriteLine(GetFilteredAnimals("Pe", GetCats));
}
private static List<Cat> GetCats()
{
return new List<Cat>() { new Cat { Name = "Sphinx" }, new Cat { Name = "Persian" } };
}
private static List<Dog> GetDogs()
{
return new List<Dog>() { new Dog { Name = "Bulldog"}, new Dog { Name = "Dalmatian" } };
}
private static List<Animal> GetFilteredAnimals(string f, Func<List<Animal>> method)
{
var animals = method();
return animals.Where(a => a.Name.StartsWith(f)).ToList<Animal>();
}
}
The method
GetFilteredAnimals("Pe", GetCats)
does not work because GetCats does not return list of Animal. Is it possible to do such generic method for lists? As far as I know, if I used single objects instead of lists it would work.
The working code for this is here on .NET Fiddle
Assuming you're using C# 4+ and .NET 4+, you can get this to work using generic covariance:
private static List<Animal> GetFilteredAnimals(string f, Func<IEnumerable<Animal>> method)
A List<Cat> can't be treated as a List<Animal> - but it can be treated as an IEnumerable<Animal> because IEnumerable<T> is covariant in T.
Likewise Func<T> is covariant in T, so a Func<List<Cat>> can be treated as a Func<IEnumerable<Animal>>... so it then compiles.
In the following example, why can't I cast collectionA to collectionB given that the compiler knows that a TItem is a A<T>?
public class A<T>
{
}
public void Foo<TItem, T> () where TItem : A<T>
{
var collectionA = new List<TItem>();
var collectionB = (List<A<T>>)collectionA; // "Cannot cast" error here
}
The problem is that it would allow you to place inappropriate items into collectionA.
Here's a simplified reworking of it, which hopefully makes it easier to see the problem:
Suppose you have (pseudocode):
class Animal {...}
class Dog: Animal { Bark(){} }
class Cat: Animal { Meow(){} }
Now imagine you could do this:
var dogs = new List<Dog>();
dogs.Add(new Dog());
dogs[0].Bark();
var animals = (List<Animal>) dogs;
Then you would be able to do this:
animals.Add(new Animal()); // Adds an Animal to the list 'dogs', which 'animals' references.
dogs[1].Bark(); // dogs will now have two elements, but the second isn't a dog -
// so calling Bark() will explode.
I believe it's because you're instructing the system to convert from List<X> to List<Y> rather than saying that you want to cast each item within the list from X to Y.
You can do this though:
public class A<T>
{
}
public void Foo<TItem, T>() where TItem : A<T>
{
var collectionA = new List<TItem>();
var collectionB = new List<A<T>>(collectionA.ToArray());
}
You want to use either
var collectionB = collectionA.OfType<List<A<T>>>();
or
var collectionB = collectionA.Cast<List<A<T>>>();
The first will ignore anything that's not of type List<A<T>> and can't be treated as it. The second will throw an exception if there's something in the list which can't be converted.
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.