Can you give me an almost overly simplistic understanding of abstract class vs inheritance use and help me so I can truly understand the concept and how to implement? I have
EDIT:
I have taken the body of code for each class out - If you want to see my answer, have a look at the edit revisions :)
First off we define the interface
public interface IAnimal
{
string WhatAmI { get; }
string WhatIsMyName { get; }
}
Any class that implements this interface must implement these properties. An interface is like a contract; a class implementing an interface agrees to provide an implementation of the interface's methods, properties events or indexers.
Next, we need to define your abstract Animal class
public abstract class Animal : IAnimal
{
//Removed for Training, See Edit for the code
}
The fact that the class is abstract indicates that the class is intended only to be a base class for other classes. We have implemented both properties of the interface and also have a private field to store the animal name. In addition, we have made the WhatAmI
property accessor abstract so that we can implement our own specific property accessor logic in each derived class and have also defined a constructor that accepts a string argument and assigns the value to the _name
private field.
Now, let's define our Cat
and Dog
classes
public class Dog : Animal
{
//Removed for Training, See Edit for the code
}
public class Cat : Animal
{
//Removed for Training, See Edit for the code
}
Both classes inherit from Animal
and each has a constructor that defines a string argument and passes that argument as a parameter to the base constructor. In addition, each class implements it's own property accessor for WhatAmI
, returning a string of their type, respectively.
For the rest of the code
public class Program
{
public static void DescribeAnimal(IAnimal animal)
{
Console.WriteLine("My name is {0}, I am a {1}", animal.WhatIsMyName, animal.WhatAmI);
}
static void Main(string[] args)
{
Dog mydog = new Dog("Spot");
Cat mycat = new Cat("Felix");
DescribeAnimal(mydog);
DescribeAnimal(mycat);
Console.ReadKey();
}
}
the static method DescribeAnimal
accepts an IAnimal
as an argument and writes out the values returned by the WhatIsMyName
and WhatAmI
property accessors for the passed in IAnimal
.
Since Animal
implements IAnimal
and both Dog
and Cat
inherit from Animal
, any Cat
or Dog
object can be passed as a parameter to the DescribeAnimal
method.
I hope that I have explained this clearly, If anyone feels my choice of words needs tightening up, please comment and I will be happy to edit my answer.
You're close, but making this tougher than it needs to be.
I don't want to give you the answer ;) but here are a few pointers.
First, you're creating 3 classes and 1 interface. However, the one thing I believe you may be missing is that you need 3 different types of objects here (from "least defined" to "most defined"):
1) Interface
This is IAnimal - and can be implemented by anything that can act like an animal
2) Abstract Base Class This is the Animal calss - anything that IS an animal should derive from Animal, but these aren't creatable directly. If you pretend you're God, you don't make an Animal, you make a Dog, Cat, Squirrel, or FuzzyBunny
3) Concrete Implementation of Animal These are the actual classes themselves. This is what you create. Dog or Cat in your case.
The trick here is that you can only create concrete classes, but you can use IAnimal or Animal (interfaces or abstract base classes) to manipulate and work with any animal (or, in the case of interfaces, anything that acts like an animal)
Another suggestion - (slightly off topic, but still related)
I recommend, for learning purposes, to avoid automatic properties. It will help you understand what's happening if you implement them explicitly.
For example, instead of doing:
class SomeClass
{
public string MyProperty
{
get;
set;
}
}
Try implementing this yourself:
class SomeClass
{
public string MyProperty
{
get
{
return "MyValue"; // Probably a private field
}
set
{
// myField = value; or something like that
}
}
I mention this because it will help you in this specific case. Since you're using automatic properties, the compiler is "filling in the blanks" for you, and in your case, I think it's preventing you from getting some very useful compiler errors. When trying to understand how these concepts work, doing the work yourself usually makes it easier, not harder.