SE251:StudentClarifications:Lec5
Lecture 5 - Object Oriented Programming 1
Inheritance
In your first lab you wrote a class that inherits from JApplet. You did this by writing:
class MyApplet extends JApplet { // stuff }
This means that MyApplet automatically contains all the functionality (methods and members) that JApplet has.
This is usually used to represent real world relationships between objects. A class Cat would extend a class Animal, because Cat is a type of Animal. Animal would contain methods and members common to all animals, and Cat would add functionality specific to cats. A class represents a type of thing. So when you're making a class, you should think "Is this a more specific type of thing that some other class?" If it is, then it should extend that other class. More commonly, you will write two classes (say, Cat and Dog) and you'll realise that they have a lot of code in common. So you'll create a new class Animal, put the code that's common between Cat and Dog inside Animal, and make Cat and Dog extend Animal.
Method overriding
If you write a method (say, makeNoise()) in Cat which is also in Animal, when you call that method Java will check if the object is a Cat or an Animal and call the appropriate method. Confusion arisis from the fact that a Cat is a type of Animal. If you had not written makeNoise in Cat, it would have called the makeNoise in Animal (since Cat extends Animal, it has that method).
Polymorphism
Things get worse. You can store a Cat in a pointer of type Animal, like this:
Animal a = new Cat();
When you do this, you can only call methods on a and use members of a if they are in the Animal class. But, if you call a method on a that is in both Animal and Cat, it will still check whether a is an Animal or a Cat, find that it's actually a Cat (even though the pointer is of type Animal) and it will call the method in Cat.
Why is this useful? Well, say you had a Cat and a Dog. Cat has a makeNoise method which meows and Dog has a makeNoise method that barks. They both extend (inherit from) Animal, which has a makeNoise method which does nothing. So you can write code that works for all types of animals, like this:
class User { public void abuseAnimal(Animal a) { a.makeNoise(); } }
Then if we use it like this:
User u = new User(); Animal a = new Cat(); u.abuseAnimal(a); // You will hear a meow.
Or, with the dog:
User u = new User(); Animal a = new Dog(); u.abuseAnimal(a); // You will hear barking.
Or boringly, with the animal:
User u = new User(); Animal a = new Animal(); u.abuseAnimal(a); // You will hear nothing.
Abstract classes
In the example above, creating an Animal doesn't make that much sense. I mean, it's really an abstract category of things, not something that can exist in it's own right. Since creating animals doesn't make much sense, we might want to make it an error. That way if someone does it by accident, it will be much easier to figure out what went wrong. To do this in Java, you declare the class as abstract, like this:
public abstract class Animal { // Stuff. }
Or, you might have a method like makeNoise which doesn't actually do anything in the Animal class, but needs to be there so that you can get animals to make noises without knowing what exactly they are. An empty method will work, but if you want (or need) to force all child classes to implement a method you can make it abstract, making it an error to call the method. If a class has an abstract method, it must be an abstract class. You write an abstract method like this:
public abstract class Animal { public abstract void makeNoise(); }