Object Oriented programming is a very important concept to both understand, and know how to utilize. I haven't had much of a use for it personally yet as I haven't undertaken any large projects that would require it; but I plan to!
For those of you who are unfamiliar with OO programming, in short - it's a way to group variables and functions into a class, which after being initiated itself, becomes an object. In example, say we want to compose an "animal" object - what kind of variables and methods (functions within a class) would that animal have? Or in layman's terms, how would we describe the animal - and what would it do?
Well since we're being generic, we can say every animal has:
Gender (Those sex changing frogs in Jurassic Park don't count right now guys.)
An animal class would look something like this (C++):
private:
string Color, Gender;
int Size;
public: string getColor() { return Color; } setColor(string c) { Color = c; } string getGender() { return Gender; } setGender(string g) { Gender = g; } int getSize() { return Size; } setSize(int s) { Size = s; } virtual void Eat() { cout << "The animal eats the food." << endl; } virtual void Sleep() { cout << "The animal goes to sleep." << endl; } virtual void Crap() { cout << "The animal... nevermind." << endl; } };
Awesome! We have an animal! But what kind of animal is it? Well right now, it's just "an animal" and it isn't anything specific; but that's what we have inheritance for. Inheritance allows us to use a previous class, and expand on it to either alter it's original form - or add something new!
For example, we now want to create a dog object. Well we know a dog is an animal, let's just extend (inherit) our animal class. But a dog has a trait that we want to add - Breed; and we want to make sure it can bark! A dog class would look like this:
class Dog : public Animal {
public:
void setBreed(string b) { Breed = b; }
string getBreed() { return Breed; }
void Bark() { cout << "Woof!" << endl; }
void Eat() { cout << "The dog eats the food." << endl; }
void Crap() { cout << "You're cleaning that up." << endl; }
};
A few points of interest here, notice how we're making the Bark() method just as we normally would and that it doesn't exist in the original Animal class; Eat() and Crap() were both in the original class; however now the statements have changed - and the 'virtual' in front of it is gone! We've also added Breed but Size, Gender, and Color aren't there, and neither is Sleep()!
Inheritance allows us to build upon our base class (Animal) and make a new, derived class (Dog) with either completely new information - or as originally stated, just altered information.
Armed with this knowledge, if we made a new Dog object, we would be able to call the following:
Dog myDog;
myDog.setColor("grey");
myDog.setSize(24);
myDog.setGender("male");
myDog.setBreed("Boxer");
cout << "My Dog is a " << myDog.getGender() << " " << myDog.getColor() << " " << myDog.getBreed() << " and is " << myDog.getSize() << " inches." << endl;
myDog.Bark();
myDog.Eat();
myDog.Crap();
myDog.Sleep();
Output:
My dog is a male grey boxer and is 24 inches.
Woof!
The dog eats the food.
You're cleaning that up.
The animal goes to sleep.
The dog was able to use the same variables that the Animal class has such as Color, Size, and Gender - but added on Breed. It was also able to access the same methods, but alter them, and in the case of Sleep(), use the original!
What's all the public/private/virtual nonsense though?!
Declaring something public within a class means that you can access the information directly by calling it on the object. In example, if we had "Color" as public within the Animal class, we would be able to call ' myDog.Size = "9000" ' straight from our code! If a variable is marked as private, it means that only methods within the class can alter it.
But if we have a variable marked as private - how exactly do we change it then? We use 'getter' and 'setter' methods. For example for Breed, which is a private variable, we have 'setBreed()' and 'getBreed' - The naming of these is arbitrary, but it's good practice to name the methods as such as we know what they do! If you look at our code, these methods do exactly as you would think - they set Breed to the parameters given in setBreed() and getBreed() let's us know what the variable is!
But why on Earth would we want to go through so much trouble? This process is called "Encapsulation" - It's the process of hiding our data so that we can make sure the end user does not break our program by providing bad data. Like stated earlier, ' myDog.Size = "9000" ' , surely there is no dog in existence that is anywhere near ( or OVER 9000! ) inches! Well we could alter our setSize() method to be:
if (x > 200) {
cout << "Your dog isn't that big! Make it smaller!" << endl;
cout << "Please enter a new value: ";
cin >> x;
setSize(x);
Now we can't have a dog be greater than 199 inches; but wait a minute - it's not compiling! Well it looks like we have a few errors in our code. Remember those weird "virtual" functions? Those basically mean that a derived class is allowed to make changes to the base classes code; if these were not declared virtual - then when we called method, it would run the base class's version of the method! Let's go ahead and add "virtual" infront of all of our set() methods in case we want to make more changes later!
While we're discussing virtual functions, I want to mention pure virtual functions - which means that a method *must* be derived in a child class. We can do this by making a prototype in the base class such as ' virtual void pure_virtual() = 0; ' .
Now, back to our dog example: You'll notice that even after changing our method to virtual, we're still receiving a compiler error! Well actually, the virtual method wasn't even throwing a compiler error - we were just preventing an error from runtime; the real error that we're running into is that we originally set the "Size" variable to be private in the Animal class. As we mentioned earlier, private means that only methods in the same class can alter it's variable, meaning something like "Animal.setSize(), but not "Dog.setSize()". In order to fix this, we will need to make the variable protected so that a derived class can also have access to this variable!
Head back up to our Animal class and simply adjust the "private:" to "protected:" and we're all set!
If anyone has any questions ( Or I made an error :) ) let me know and I'd be happy to talk!
The complete source code for the examples I wrote can be found here: http://ThomasBiddle.com/Animal.txt