What are some practical examples of abstract classes in java?

When and why should abstract classes be used? I would like to see some practical examples of their uses. Also, what is the difference between abstract classes and interfaces?

38.7k 11 11 gold badges 256 256 silver badges 219 219 bronze badges asked Oct 2, 2009 at 14:15 266k 266 266 gold badges 586 586 silver badges 779 779 bronze badges

Perhaps because it is a question that is so easily answered by a simple internet search. Just guessing.

Commented Oct 2, 2009 at 14:26

@Bart: An internet search would just give jim abstract classes; not good examples that help understand the concept.

Commented Oct 2, 2009 at 14:28

Agreed, a very sensible question. I think it's actually one of those questions that are more complex than one might think at first.

Commented Oct 2, 2009 at 14:30 How about AbstractList in the jdk? AbstractSet. Commented Oct 2, 2009 at 16:35

10 Answers 10

Abstract classes are "half-implementations" of a class. They can be partially implemented with some generic functionality, but leave part of the implementation to the inheriting classes. You could have an abstract class called Animal that has implemented some generic behavior/values such as Age , Name , SetAge(. ) . You can also have methods that are not implemented (they are abstract ), much like an interface.

Interfaces are simply contracts that specify behaviors that should be available for a class. You could have an interface such as IWalker that requires public method Walk() , but no specifics on how it is implemented.

answered Oct 2, 2009 at 14:20 50k 13 13 gold badges 122 122 silver badges 154 154 bronze badges

Classes that are entirely abstract (all methods are abstract) are (almost) the same as interfaces (the major difference being they can contain fields and non-public abstract methods, which interfaces cannot). The difference is when you have an abstract class which contains a method which has some common functionality which will be the same for all derived children.

If you want to model a Filesystem, for example, you know that, regardless of the object type, you will have a path for an item. You'd want to have a common implementation for getting that path (no point in writing the same thing over and over again), and leave anything special for the children to implement.

answered Oct 2, 2009 at 14:21 7,322 4 4 gold badges 36 36 silver badges 43 43 bronze badges

Nitpick: Classes that are entirely abstract are not the same as interfaces - abstract classes can contain fields, which interfaces cannot, and interfaces allow multiple inheritance, while (abstract) classes do not.

Commented Oct 2, 2009 at 14:28

Abstract Classes versus Interfaces

Unlike interfaces, abstract classes can contain fields that are not static and final , and they can contain implemented methods. Such abstract classes are similar to interfaces, except that they provide a partial implementation, leaving it to subclasses to complete the implementation. If an abstract class contains only abstract method declarations, it should be declared as an interface instead.

Multiple interfaces can be implemented by classes anywhere in the class hierarchy, whether or not they are related to one another in any way. Think of Comparable or Cloneable , for example.

By comparison, abstract classes are most commonly subclassed to share pieces of implementation. A single abstract class is subclassed by similar classes that have a lot in common (the implemented parts of the abstract class), but also have some differences (the abstract methods).

An Abstract Class Example

In an object-oriented drawing application, you can draw circles, rectangles, lines, Bezier curves, and many other graphic objects. These objects all have certain states (for example: position, orientation, line color, fill color) and behaviors (for example: moveTo, rotate, resize, draw) in common. Some of these states and behaviors are the same for all graphic objects—for example: position, fill color, and moveTo. Others require different implementations—for example, resize or draw. All GraphicObjects must know how to draw or resize themselves; they just differ in how they do it. This is a perfect situation for an abstract superclass. You can take advantage of the similarities and declare all the graphic objects to inherit from the same abstract parent object—for example, GraphicObject , as shown in the following figure.

Classes Rectangle, Line, Bezier, and Circle inherit from GraphicObject

[. ]

22.5k 13 13 gold badges 88 88 silver badges 116 116 bronze badges answered Oct 2, 2009 at 14:31 Pascal Thivent Pascal Thivent 569k 140 140 gold badges 1.1k 1.1k silver badges 1.1k 1.1k bronze badges

Surprisingly, many examples/explanations given here do not provide good arguments for using an abstract class. Merely putting common fields/methods in a superclass does not require it to be abstract. Also (start rant), shame on supposedly knowledgeable engineers still coming up with Animal / Vehicle / Figure hierarchies to 'explain' object oriented concepts. These types of examples are very misleading because they point you in the wrong direction; you generally should NOT favour straight subclassing because it creates a very tight coupling between the classes. Rather use collaboration (rant ends).

So what do I think is a good use case for an abstract class? One of my favorite examples is an application of the 'template method' GoF pattern. Here you want to specify the generic flow of an algorithm once, but allow multiple implementations of the individual steps. Here an example I just put together of a VirusScanEngine containing the main virus scanning algorithm (find the next virus, either delete or report it, continue until scan is complete), and a LinearVirusScanner which implements the required algorithm steps (findVirus, deleteVirus and reportVirus). My apologies to all developers really working on virus scanning software for this horrendous simplification.

import java.util.Arrays; public abstract class VirusScanEngine < public static void main(String[] args) < byte[] memory = new byte[] < 'a', 'b', 'c', 'M', 'e', 'l', 'i', 's', 's', 'a' , 'd', 'e', 'f', 'g'>; System.out.println("Before: " + Arrays.toString(memory)); new LinearVirusScanner().scan(memory, Action.DELETE); System.out.println("After: " + Arrays.toString(memory)); > public enum Action < DELETE, REPORT >; public boolean scan(byte[] memory, Action action) < boolean virusFound = false; int index = 0; while (index < memory.length) < int size = findVirus(memory, index); if (size >0) < switch (action) < case DELETE: deleteVirus(memory, index, size); break; case REPORT: reportVirus(memory, index, size); break; >index += size; > index++; > return virusFound; > abstract int findVirus(byte[] memory, int startIndex); abstract void reportVirus(byte[] memory, int startIndex, int size); abstract void deleteVirus(byte[] memory, int startIndex, int size); > 
public class LinearVirusScanner extends VirusScanEngine < private static final byte[][] virusSignatures = new byte[][] < new byte[] < 'I', 'L', 'O', 'V', 'E', 'Y', 'O', 'U' >, new byte[] < 'M', 'e', 'l', 'i', 's', 's', 'a' >>; @Override int findVirus(byte[] memory, int startIndex) < int size = 0; signatures: for (int v = 0; v < virusSignatures.length; v++) < scan: < for (int t = 0; t < virusSignatures[v].length; t++) < if (memory[startIndex + t] != virusSignatures[v][t]) < break scan; >> // virus found size = virusSignatures[v].length; break signatures; > > return size; > @Override void deleteVirus(byte[] memory, int startIndex, int size) < for (int n = startIndex; n < startIndex + size - 1; n++) < memory[n] = 0; >> @Override void reportVirus(byte[] memory, int startIndex, int size) < System.out.println("Virus found at position " + startIndex + " with length " + size); >>