The BASE for JAVA LEARNING

by PRO FE S S OR


SECTION XII - Interfaces and Abstract Classes

Step 49: An Abstract class

ABSTRACTION

Before we discuss what an abstract class is, it would be convenient to click on ABSTRACTION and have some general understanding of the benefits of it.

First, let's disccuss what is an abstract method.


An Abstract Method

An abstract method is a method that does not define code. It's a prototype used as a placeholder. Since it does not have code its purpose is for interface only. Even though it does not contain code, it portrays the arguments within the set of parentheses and the return type. By providing name, arguments and return type, the method conveys what it does. But it does not convey how does it do it.

An Abstract Class

An abstract class is a class that contains at least one abstract method. A class can contain many methods, but if only one method out of many is abstract, the class becomes abstract.

An Example of a abstract method defined within an abstract class abstract class Document // notice the 'abstract' keyword
{ abstract double process(double arg1, double arg2); // notice the 'abstract' keyword

void concreteProcess() // this is a regular non-abstract method
{ // code goes here }
}
The method above named 'process' conveys the fact that two 'double' values are processed, and as a result of that, an integer will be returned. The abstract method let us know about the "what", not the "how".

Notice that there is no code defined in the abstract method, and it ends in semi-colon.

A class can also contains all of its methods abstract.. Such a class with all abstract methods is used only for interface. (An Interface as discussed in next Step is a total abstract class.

An abstract class can not be instantiated. That is, no Object can be created directly from it. However, an abstract class can have sub-classes that are not abstract.


You may wonder what's the idea of having an abstract method. When there is an abstract method, it means that there ought to be a method with the same name, and same signature (arguments and return type) in a derived class. That method in that derived class is concrete (not abstract) and contains the code for its implementation.

By virtue of Inheritance (discussed in Section X), if a class that derives (inherits) from an abstract super-class is instantiated, all the concrete methods of the super-class can be implemented (executed) via this child class.

An abstract method in an abstract super-class is used as the prototype, but the method of the child class (if concrete) is the one that is implemented. (sort of mandatory Overriding). This counterpart method in the child class is defined as non abstract method (concrete), with the same signature, name and return type of the abstact method. If it's not defined as a concrete method in the child class, it has to be defined as concrete method in the grand-child class or in any other lower level hierarchy class.

In a hierarchy (Inheritance) scheme, if the method declared abstract in the super class, is not defined as concrete in any of the lower level classes (child, grandchild, great-grandchild, etc), a compiler error would occur. Now, it is possible that the method is also made abstract in the child class. If that's the case, then it still needs to be defined as concrete method in the grand-child class or any lower level hiearchy class.

This may seem a little bit confusing, so we will illustrate various scenarios with Examples.


Example 1

(In this Example the process' method is declared abstract in the super class, and its counterpart method IS NOT defined in the child class.) /*
  • An abstract super-class with an abstract method
  • A child class where that abstract method of its super class is not defined.
  • A compiler error would occur. (as the abstract method is not defined.)
*/
abstract class Document
{ int number;
abstract void process(); // an abstract method
void setNumber(int tmpNumber) // a concrete method
{ // code goes here }
}

class Notebook extends Document // this is the child class.
{ void scribble() // a concrete method
{ // code goes here }
}
A compiler error occurs above as the child class "Notebook" does not define the abstract method stated in the super class "Document".


Example 2

(In this Example the compilation error of Example 1 above is corrected, by defining the 'process' method in the childe class.) /*
  • An Astract super-class with an abstract method
  • A child class with a concrete method that defines the super class abstract method.
  • A 'main' method in the Document class where a child class Object is instantiated.
*/
abstract class Document
{ int number;
public static void main(String[] args)
{ Notebook agenda = new Notebook(); // ' agenda' is a child class Object.
agenda.setNumber(5); // this class method is invoked here via the child Object.
agenda.process(); // method as implemented in the child class is invoked here.
}

abstract void process(); // an abstract method
void setNumber(int tmpNumber) // a concrete method
{ // code goes here }
}

class Notebook extends Document // this is the child class.
{ void process() // this concrete method is the counterpart of the super class abstract method.
{ // code goes here }

void scribble() // a concrete method
{ // code goes here }
}


Example 3

(In this Example the 'process' method is declared as abstract in the super class, non-existing in the child class, but defined concretely in the grandchild class.) /*
  • An Astract super class with an abstract method
  • A child class with NO counterpart method of the super class abstract method.
  • A grandchild class with a concrete method that defines the top level super class abstract method.
  • A 'main' method in the Document class where a child class Object and a grandchild class Object are instantiated.
*/
abstract class Document
{ int number;
public static void main(String[] args)
{ Notebook agenda = new Notebook(); // ' agenda' is a child class Object.
agenda.setNumber(5); // this class method is invoked here via the child Object.

Magazine guide = new Magazine(); // ' guide' is a grandchild class Object.
guide.process(); // method as implemented in the grandchild class is invoked here.
}

abstract void process(); // an abstract method
void setNumber(int tmpNumber) // a concrete method
{ // code goes here }
}

class Notebook extends Document // this is the child class.
{
void scribble() // a concrete method
{ // code goes here }

class Magazine extends Notebook // this is the grandchild class.
{ void process() // the counterpart concrete method of "Document" super class abstract method.
{ // code goes here }
}


Example 4

(In this Example the 'process' method is declared as abstract in the super class, declared also as abstract in the child class, but defined concretely in the grandchild class.) /*
  • An Astract super-class with an abstract method
  • A child class with an abstract method same name, same return type of the one in the super-class.
    (As there is an abstract method in this child class, it's also abstract, and can't be instantiated.)
  • A grandchild class with a concrete method that defines the top level super class abstract method.
  • A 'main' method in the Document class where the grandchild class Object is instantiated.
*/
abstract class Document
{ int number;
public static void main(String[] args)
{ Magazine guide = new Magazine(); // ' agenda' is a grandchild class Object.
guide.setNumber(5); // this class method is invoked here via the grandchild Object.

guide.process(); // method as implemented in the grandchild class is invoked here.
}

abstract void process(); // an abstract method
void setNumber(int tmpNumber) // a concrete method
{ // code goes here }
}

abstract class Notebook extends Document // this is the child class.
{
abstract void process(); // abstract method

void scribble() // a concrete method
{ // code goes here }
}

class Magazine extends Notebook // this is the grandchild class.
{ void process() // the counterpart concrete method of "Notebook" child class abstract method.
{ // code goes here }
}
As you from above Example, an abstract class cannot be instantiated. However, an abstract class has a Constructor. It needs to be Constructor-enabled because of Inheritance. When an Object of a child class is created, JAVA follows the process of invoking the top level default Constructor first, and then continues down the hierarhy. (See Section X, Step 42: Constructor Invocation at different Hierarchy Levels.)


Click here to go to the JAVA Mini-Course page


The BASE for JAVA LEARNING

by PRO FE S S OR


SECTION XII - Interfaces and Abstract Classes

Step 50: Interfaces

INTERFACES

An Interface

Different from an abstract class, an Interface cannot be inherited by any class, ot it cannot inherit another class. It can only have classes that conform to it. (A class 'implements' an interface)

However, even though an interface cannot be inherited by any class, it can indeed be inherited by or inherit another interface. We can say that an interface can be sub-interfaced. An example of that is the JAVA interface 'Paint' which extends the 'Transparency' interface.

As previously stated all method in an interface are abstract and public. As that's the case, we do not need to use the keyword 'abstract' or the keyword 'public'. It is optional. However, it may be a good idea to write the keyword 'abstract' because that emphasizes the fact that the method is abstract.

By the same token, all attributes (variables) are 'final' , 'static', and 'public'. Therefore keywords 'static' or 'final' or 'public' are not needed. They are optional. It may be a good idea to write the keyword 'final' to emphasize the fact that the attribute is final.

As the attributes are final, they are initialized at the time of declaration.

Example of an interface with some attributes (constants) defined and methods declared:
interface Processable
{ final int year = 2002; // 'final' keyword is optional here
final StringBuffer message = new StringBuffer("Welcome"); // 'final keyword is optional here

abstract void process(); // 'abstract' keyword is optional here
abstract int remove(int tmpNumber); // 'abstract' keyword is optional here
}
Usually when we have an interface, we want classes that conform to that interface. In order to have a class that conform to an interface we use the keyword 'implements' on the class.

See Example below:
interface Processable
{ // interface definitions of attributes and abstract methods declaration go here }

class Algorithm implements Processable
{ // class definition goes here }

It is conventional to name interfaces with names that imply abstraction. Those names that ends with the suffix "able", imply abstraction, as for example "Processable", "Interchangeable", "Measurable", etc.


A class implementing interface(s)

The abstract methods declared in the interface will have to be implemented concretely in any class that conforms to that interface. If any method is missing from the class that implements the interface, then that method has to be implemented by a derived or lower-level hierarchy class of that class. Otherwise, a compiler error would occur.

If multiple classes implement an interface, all of them will have to implement the methods of that interface independently. In the absence of the methods from the those implementing class, some lower hierarchy level class will have to implement them. If concrete methods are not found anywhere in the hierarchy downward path, a compiler error would occur.

Let's have some Examples to illustrate this. To be provided later.....


Click here to go to the JAVA Mini-Course page



The BASE for JAVA LEARNING

by PRO FE S S OR


SECTION XII - Interfaces and Abstract Classes

Step 51: Implementing Multiple Interfaces

Implementing Mutliple Interfaces

When we discussed Inheritance (Section X) we learned that there is no Multiple Inheritance, that is, any class cannot have more than one parent.

For interfaces, this is not case, as a class can conform (implement) to many interfaces.

The advantage of that is tremendous. There are many JAVA classes that implement more than one interface. JAVA has a set of interfaces called "Listeners" which are Event Handlers. It is possible to have a class than impolement two Listeners, and that is very convenient. When we are developing a GUI for instance, we may want that GUI to implement the WindowListener and the ActionListener interfaces. Each of this interface has methods that can be used to generate a specific behavior for that GUI.

All the abstract of the interfaces will have to be defined by the class. So if the class implement 3 interfaces, it has to define all the abstract methods of all those 3 interfaces, and it can utilize all the constants defined in those 3 interfaces.

Here below see an Example of a class that implement two interfaces. Both interfaces have attributes and abstract methods. class Exercise implements Processable, Measurable
{ public void process()
{ System.out.println(year); // year 2001 defined in interface Processable is displayed.
// code continues here
}

public void measure()
{ System.out.println(timeDelay); // timeDelay 100 defined in interface Measurable is displayed.
// code continues here
}

// class definition continues here
}

interface Processable
{ int year = 2001; // this constant can be used by any class implementing this interface.
void process(); // method declared here - public and abstract
}

interface Measurable
{ int timeDelay = 100; // this constant can be used by any class implementing this interface.
void measure(); // method declared here - public and abstract
}
The Exercise class above can utilize all the constants as defined in both interfaces 'year' and 'timeDelay', and it defines all the abstract methods declared in both interfaces, 'process()' and 'measure()'.

If there are constants with the same name in both interfaces, then an "ambiguity" error would occur when compiling.

However, we can have same name abstract methods in both interfaces, and that would not give any compiler error, as the methods declared in the interfaces are only prototypes, and they serve as guidelines for the methods in the class to be defined.


Click here to go to the JAVA Mini-Course page





The BASE for JAVA LEARNING

by PRO FE S S OR


SECTION XII - Interfaces and Abstract Classes

Step 52: Why INTERFACES?

Purpose of an interface

As you can infer from our discussion on interfaces, one idea about having interfaces is to have more loosely-coupled classes.

Suppose a programmer is developing a class that needs to do some interfacing with several classes related among themselves. If those related classes can all have an "interface" from which they implement, then the programmer instead of directly couple his or her class towards those classes directly and independently, he or she can do the coupling to the interface.

By doing so, a more de-coupling environment will be achieved. In Object-Oriented programming we want to have high de-coupling.

It is important that developers program towards the interface and not to other classes. Of course if there is no interface available, it may be convenient to look into creating one, and make the related classes implement that interface.

Let's say that there are 3 classes: Book, Notebook and Pamphlet classes. You are coding a class named Topic upon which Objects of those three classes are to be passed. If there is no Interface to which those three classes conform, in your Topic class you would have to write three different Constructors. One Construct would capture a Book Object, another Constructor would capture a Notebook Object, and the other Constructor would capture a Pamphlet Object.

However, if those three classes implement a common Interface, then in your Topic class, you only would need one Constructor that would capture that Interface. Then, that Interface would be used to reference a Book Object, a Notebook Object or a Pamphlet Object as the case may be.



The Example 1 below shows the Book, Notebook and Pamphlet classes, and the Topic class, with no Interface used. Three Constructors are used in the Topic class for capturing Object of those three classes.

Then in Example 2 an Interface will be written named Readable and these 3 classes will conform to it. Then the code in the Topic class can be changed to have only one Constructor. That argument of that Constructor is the Interface reference, which is then used to capture either a Book Object, or a Notebook Object, or a Pamphlet Object.

Notice that by having the Interface, if later in the future you want to include another related class, (say the Brochure class which implements Readable) it can be done without having to write an additional Constructor in the Topic class. More de-coupling is achieved.

Example 1:

(with no Interface) class Topic
{ Topic(Book tmp)
{ // code goes here to capture Book Object. }

Topic(Notebook tmp)
{ // code goes here to capture Notebook Object. }

Topic(Pamphlet tmp)
{ // code goes here to capture Pamphlet Object. }

}

class Book
{ Book()
{ new Topic(this); }
}

class Notebook
{ Notebook()
{ new Topic(this); }
}

class Pamphlet
{ Pamphlet()
{ new Topic(this); }
}



Example 2:

(with an Interface) class Topic
{ Topic(Readable tmp)
{ // code goes here to capture Book, Notebook, or Pamphlet Object. }

}

interface Readable
{ // final Variables, and abstract methods defined here }

class Book implements Readable
{ Book()
{ new Topic(this); }
}

class Notebook implements Readable
{ Notebook()
{ new Topic(this); }
}

class Pamphlet implements Readable
{ Pamphlet()
{ new Topic(this); }
}

More classes that conform to the Readable Interface can be included in Example 2 above, with no need to add another Constructor in the Topic class. The Topic class has been coded to the Interface, not to the individual classes, as it was the case in Example 1.




Click here to go to the JAVA Mini-Course page