Interfaces and abstract classes provide a more structured way to separate interface from implementation.
Such mechanisms are not that common in programming languages. C++, for example, only has indirect support for these concepts. The fact that language keywords exist in Java indicates that these ideas were considered important enough to provide direct support.
Abstract class: a kind of midway step between an ordinary class and an interface. Although your first impulse is to create an interface, the abstract class is am important and necessary tool for building classes that have fields and umimplemented methods. You can't always use a pure interface.
For an abstract class, objects of that specific class almost always have no meaning. You create abstract class when you want to manipulate a set of classes through its common interface. Thus, abstract class is meant to express only the interface, and not a particular implementation, so creating an object that is only an abstract class makes no sense, and you'll probaly want to prevent the user from doing it. This can be accomplished by making all the methods in abstract class generate errors, but that delays the information until run time and requires reliable exhaustive testing on the user's part. It's usually better to catch problems at complie time.
Java provieds a mechanism for doing this called the abstract method. This is a method that is imcomplete; it has only a declaration and no method body. Here is the syntax for an abstract method declaration:
abstract void f();
A class containing abstract methods is called an abstract class. If a class contains one or more abstract methods, the class itself must be qulified as abstract, otherwise, the compiler prodeces an error message.
//interfaces/Basic.java
abstract class Basic{
abstract void unimplemented();
}
If an abstract class is incomplete, what is Java supposed to do when someone tries to make an object of that class? It cannot safely create an object of an abstract class, so you get an error message from the complier. This ensures the purity of the abstract class, and you don't worry about misusing it.
//interfaces/AttemptToUseBasic.java
//{Will not compile}
public class AttemptToUseBasic{
Basic b= new Basic();
//error:Basic is abstract; cannot be instantiated
}
If you inherit from an abstract class and you want to make objects of the new type, you must provide method definitions for all the abstract methods in the base class. If you don't (and you might choose not to), then the derived class is also abstract, and the complier will force you to qualify that class with the abstract keyword.
//interface/Basic2.java
abstract class Basic2 extends Basic{
int f(){ return 111; }
abstract void g();
//unimplementd() still not implemented
}
It's possible to make a class abstract without including any abstract methods. This is useful when you've got a class where abstract methods don't make sense, and yet you want to prevent any instances of that class.
//interfaces/AbstractWithoutAbstracts.java
abstract class Basic3{
int f() { return 111; }
//No abstract methods
}
public class AbstractWithoutAbstraces{
//Basic3 b3= new Basic3();
//error: Basic3 is abstract; cannot be instantiated
}
//interfaces/Instantiable.java
abstract class Uninstantiable{
abstract void f();
abstract int g();
}
public class Instantiable extends Uninstantiable{
@Override
void f() {System.out.println("f()");}
@Override
int g() {return 22;}
public static void main(String[] args){
Uninstantiable ui= new Instantiable();
}
}
Note the use of @Override. Without this annotation, if you don't provide the provide the exact method name or signature, the abstract mechanism sees you haven't implenented the abstract method and produces a produces a compile-time error. Thus, you could effectively argue that @Override is redundant here. However, @Override also gives the reader a signal that this method is overridden--I consider this useful, and so will ues @Override even when the complier would inform me of mistakes without it.