Interface vs. Abstract in Java

by Steven J. Owens (unless otherwise attributed)

Interface vs. Abstract in Java

Or: Why does javac tell me my class should be declared Abstract?

Before I explain the difference between interface and abstract, if you got here because your java compiler is telling you your class should be declared abstract, let's clear that up first:

Let's say you get this error:

SelectSort.java:6: SelectSort should be declared abstract; it does not define sort(jds.Indexed) in SelectSort
public  class SelectSort implements SortAlgorithm
        ^
1 error

What's happening here is that, as usual, javac's misleading error messages confuse and obfuscate things. What this means is that you're using the "implements SortAlgorithm" phrase, which tells the compiler that you want the resulting class to be marked as providing all of the methods defined in the "SortAlgorithm" interface. However, you apparently have not included code in your class to implement the "sort(jds.Index)" method.

What javac should really say is:
"Hey you! You said "implements SortAlgorithm", but you left out one of the methods of SortAlgorithm, the method "sort(jds.Indexed). So either implement sort(jds.Indexed) in your SelectSort class, or add the keyword "abstract" (before the keyword "class") so I know you weren't intending to fully implement SortAlgorithm."

So the answer to your immediate problem is to go in and implement sort(jds.Indexed). Or add the abstract keyword to your class declaration.

Interface versus Abstract, the Short Version

I have a longer description below, but I recently re-read this and realized it takes a while to get to the heart of the difference. So I'll give you the short version here, and if you don't understand it, read through the rest of this page.

The big difference is this:

Abstract is a shortcut that can be quite handy, but interface is a key concept in java's take on object-oriented programming.

An interface is a name and definition of a role that some object may play in your program. For example, a List is a role - it's an object instance that contains references to multiple other object instances, and the references can be added and removed, and the List keeps track of them in order. So if you see "implements List", then you know you'll be able to find add() and get() and so forth. More importantly, the java compiler knows it, so it knows it's legit for another class to call .add() on the class that has "implements List".

If a class has the phrase "implements SomeInterfaceName" on its declaration, that's a promise (that the java compiler enforces) that the class has all the right methods so you can just pretend it's an instance of SomeInterfaceName. The interface file defines the methods that other classes can use to interact with anything that claims to play that role (aka implement that interface).

An abstract class is a shortcut that comes in handy when you're building a hierarchy of classes and you realize that two or more classes share a lot of stuff in common and should maybe have a parent class where that code lives... ...but, there's not quite enough stuff in common that the parent class can actually be used; there are bits that you know should be there, but you can't come up with a default implementation for those bits.

So you sketch out the parent class, including method signatures for the stuff that you can't implement yet, and you put the abstract keyword on them, and now ta-da! It's an abstract class. Now you can implement the child classes with the specific behaviors, or somebody else can come along and implement child classes with behaviors you never thought of.

What implications does declaring a class abstract have?

Abstract classes in the wild are generally only found in the class hierarchies in APIs provided by Sun or other vendors. For your uses, you almost never want to create abstract classes, though you may (rarely) find yourself having to create a child of an abstract class and complete the implementation.

If you actually needed to read this, you're almost certainly not yet at a level where you should be fiddling with abstract classes. (Put that energy into learning to get comfortable with interfaces, instead.) One of the classic mistakes that new OO programmers make is getting fascinated with inheritance and making complex class hierarchies, instead of just using composition.

If you're in a college course and you instructor tells you to make your class extend a certain abstract class, what that means is that the abstract class left one or more methods unimplemented. Because you're extending (creating a subclass of) an abstract class, instead of implementing an interface, all you have to do is implement the missing bits. Your instructor is using an abstract class to provide you with a partially done problem and enable you to focus on the lesson instead of the rest of the necessary class scaffolding.

So what's the difference between an Interface and an Abstract Class?

An interface is a conceptual thing, though it does have concrete implications in Java.

You can't discuss Interfaces and Abstract Classes without first defining what a Class is. By the time you get here, you should know what a Class in java is, but just to recap, the concept of a class in OOP is that it's the description, sort of an ideal platonic form or template, of an object - and an object is a set of data (instance variables, etc) and behaviors that work on on that data (methods).

Often it's useful to look at this sort of thing and separate out the description of how you interact with the class (i.e. what methods does it have, what class variables does it have - in other words, the interface of the class) from the implementation of the class.

Note: In general the word "interface" means what you use to interact with something (well, okay, originally it meant "a surface forming a common boundary of two bodies, spaces, or phases" (Merrian-Webster Collegiate Dictonary), but the computer people stole that word).

There are various good reasons to do this. Sometimes you want different classes to play the same role but you can't just make them be children of the same parent class (because java doesn't support multiple inheritance - because java's creators felt that in languages that do support multiple inheritance, most of the time it's just used to create a big, hairy mess). Sometimes you want to allow for the possibility of different vendors to supply different implementations.

Note: The second reason happens a lot in the java APIs. They call it being "pluggable". The most common example is the JDBC API, which is mostly defined as interfaces. The different database vendors provide implementations that are customized to match their databases. You see a whole lot of this in the XML world, too, which is why learning the various SAX and DOM APIs can be a big pain in the ass (but is ultimately worth doing).

For example:
Let's say you have a class named User.
You want to build a new class, named Robot.

You don't necessarily want the Robot to be descended from User, or vice versa, but you do want other code to be able to talk to the Robot just as if it were a user. So you make sure Robot has all the same method names and takes the same arguments as User, and sends back the same types of responses.

Problem solved for now, but what if you want to possibly add more classes in the future? What if you don't want *all* of User's stuff on Robot, just some stuff? What if somebody else adds a new class that claims to be the same sort of class, claims to have all the right methods and arguments, etc, but you want to make sure?

The Answer: you define an interface for all things that you can interact with like a person in your program, let's say we call it an "Interactor". In Java, an interface is sort of passive - not like code. It just defines a set of method names, what the argument types are, and what the return types are. In other words, it defines the interface that the rest of the program will use to talk to that class.

The interface should define some common set of these methods, the ones that you'll want all Interactors to have. Then in your User and Robot classes, you add the phrase "implements Interactor" to the class definition. This tells the Java compiler to check and make sure that you've got code for all the methods in the interface, and to add the interface identifier to the class file.

Then, at some later point in time when a program loads one of your class files in, and tries to use it as an Interactor, the java environment will automatically check to see whether that class "implements Interactor" (aka has the "implements Interactor" phrase in the definition and has actual method code for all the methods).

Abstract Class

Okay, so that's an interface. Then what's an abstract class?

An abstract class is more of a functional thing than an interface. Abstract classes are for implementation - a shortcut that comes in handy during the implementation stage but which should be largely ignored during the design stage.

But let's take another case - let's say that for some reason you decide you do want Robot and User to share the same parent. All the code for the different methods is the same and you'd rather avoid having two sets of it. Okay, so you make a common superclass, let's call it "Actor" (as in something that acts within the program). You put all the common code on the Actor class and you make Robot and User descend from it (by adding the "extends Actor" phrase to their class definitions).

But wait a minute... the Actor class by itself isn't really enough to be instantiated and used. Plus, you have some methods that you know _should_ be there but you can't define them yet. In fact there are some methods that you want the Actor methods to be able to count on having access to. You want to make sure any descendents of Actor define them. So you add the declaration for these methods, plus the Abstract keyword.

Now the Java compiler will spot the "Abstract" keyword and not let anybody directly instantiate and use this class. But you can use it as a basis for extending.

Further Reading:

In general I strongly recommend anybody starting out with Java to go to www.bruceeckel.com and download the book, or better yet, to save your eyes, visit your nearest bookstore and buy a printed copy.


See original (unformatted) article

Feedback

Verification Image:
Subject:
Your Email Address:
Confirm Address:
Please Post:
Copyright: By checking the "Please Post" checkbox you agree to having your feedback posted on notablog if the administrator decides it is appropriate content, and grant compilation copyright rights to the administrator.
Message Content: