public abstract class Animal {
♦ We use the abstract keyword to declare a class abstract. ... }♦ The purpose of abstract classes is to force subclasses to implement certain methods. ♦ An abstract class cannot be instantiated (cannot create objects of it). ♦ All other functionality of the class still exists, and its fields, methods, and constructors are all accessed in the same manner. |
abstract class Animal { ... }
♦ The Animal class is declared abstract, so we cannot use the new operator on AnimalAnimal myCat = new Animal (...); // compiler error
♦ But we can still create references (like this below)Animal myCat; // this statement is OK
|
abstract class Animal { ... }
♦ What is the utility of abstract classes if we cannot create objects from them?The answer is that an abstract class does not have much use unless it is subclassed. ♦ The (abstract) parent class contains the common functionality of a collection of child classes, but the parent class itself is too abstract to be used on its own. ♦ If you are asked to paint a mammal, you would probably paint a cat, a dog, a cow, etc. If you are asked to draw a picture of something that is just a mammal, you can see how the concept of a mammal is abstract. Many animals are mammals, but no animal is just a mammal. It seems logical, therefore, that no one would need to instantiate an object of type Mammal (assuming that we wrote a Mammal class). |
♦ Suppose the following code. Class Cat extends Animal.
abstract class Animal {
void sound() {
System.out.println ("no sound");
}
}
// ─────────────────────────────────────────
class Cat extends Animal {}
// ─────────────────────────────────────────
public class Zoo1 {
public static void main (String [] args) {
Cat myCat = new Cat();
myCat.sound();
}
}
|
Output | no sound |
Comments That's fine, except the cat has a sound (niauuuu). It is obvious that we forgot to override the sound method inside the Cat class. Let's fix it:
abstract class Animal {
void sound() {
System.out.println ("no sound");
}
}
// ─────────────────────────────────────────
class Cat extends Animal {
void sound() { System.out.println ("niauuuu");
} }
// ─────────────────────────────────────────
public class Zoo2 {
public static void main (String [] args) {
Cat myCat = new Cat();
myCat.sound();
}
} |
Output | niauuuu |
Comments That's better, but still we cannot see the utility of abstraction. We would have the same result without abstraction. |
♦ Since each animal has its own sound, there is no reason for the Animal class to implement the sound method or to have any sound method at all. Each subclass can implement its own sound method. But this solution is somewhat risky. Some subclasses may forget to do that. So since parent class Animal definitely wants to be sure that his child classes will implement sound, declares this method abstract. ♦ This is how abstract methods arise.
abstract class Animal {
abstract void sound(); // no curly braces at the end
}
// ─────────────────────────────────────────
class Cat extends Animal {
void sound() {
System.out.println ("niauuuu");
}
}
// ─────────────────────────────────────────
public class Zoo3 {
public static void main (String [] args) {
Cat myCat = new Cat();
myCat.sound();
}
}
|
Output | niauuuu |
Comments Now it is impossible for the Cat subclass to forget to implement the sound method. If it forgets, the code doesn't compile. ♦ Declaring a method as abstract has two results:
|