Practical
Embedded Java

Abstract Classes


A practical engineering approach to using embedded Java in real-world applications.


...



Summary Here

What is an Abstract Class and when should I use it?

Abstract classes are useful when you want to encapsulate a set of common features in one superclass, and you want some concrete methods in the superclass itself.

If your abstract class needs no concrete methods, or you want a subclass to implement multiple superclasses, then an interface may be more appropriate.


Recommended Embedded uses

You might have an abstract Motor class, with subclasses SteeringMotor, DriveMotor, etc. This would be a good way to encapsulate Motor functionality.

Device or I/O drivers commonly use abstract classes and/or interfaces.


Tips for embedded use
  1. Consider the hardware (if any) which relates to your classes and pattern your objects after it. For example, if there is only one possible instance of the hardware (a keyboard for example), then make it a static class and don't confuse users by allowing nonsensical multiple instances.
  2. Will your API evolve over time? An interface may be the wrong choice, since every time you add new methods, you break all existing uses. Consider an abstract class or a combination of the two.
  3. Does your superclass naturally want to contain common generic methods and fields which will be useful to all users? If so, don't duplicate such code by forcing an interface on this situation - use an abstract class and create one place to maintain such shared code.

Abstract Classes vs Interfaces
 
Abstract Class
Interface
 
Abstract classes
Interfaces are just a specification or template, with no implementation.
Subclass can extend or implement multiple superclasses?
No, a Java class can extend only one superclass.
Yes, a Java class can implement any number of interfaces
What a subclass does
subclasses extend the superclass
subclasses implement the superclass
Common examples
javax.comm.CommPort
javax.comm.SerialPortEventListener, java.io.DataInput, java.io.DataOutput, java.lang.Runnable, java.util.Enumeration, javax.microedition.io such as Connection, Datagram, InputConnection, StreamConnection.
Constructor?
Yes, but be careful if you make an abstract class's constructor private, since private methods of an abstract class are not abstract.
No, since an interface cannot be instantiated.
Can contain concrete methods?
Yes
No, all methods of an interface are abstract, though they need not use the 'abstract' keyword.
Subclass must implement all (abstract) methods in superclass?
Yes, so you know that any subclass has implementations of all the abstract methods in a superclass. You'd hope that you could then count on these mehtods all working as expected in every subclass. Sadly, this is often not the case -- for example, javax.comm.SerialPort classes are often "implemented" to satisfy the superclass when in fact the implementation has no function - for example, setting options such as number of stop bits, parity, etc, which are not supported by the underlying hardware.
No, so you have no idea if a subclass implements any particular interface methods. But if a class does not implement all interface methods then it inherits any such abstract methods and the class must be declared abstract.
Can have private or protected methods?
Yes, but these must be concrete methods
No, all interface methods are implicitly public.
Subclasses can contain methods not in the superclass?
Yes, but access can be a bit tricky. I'm still looking into this.
Yes, no restrictions.
Can include fields?
Yes
Yes, but only if static and final.
Maintainability concerns
  1. If you add abstract methods to an existing abstract class, you will break any existing subclasses.
  2. Adding concrete methods does not affect existing subclasses.
If you add abstract methods to an existing interface, you will break any existing uses of that interface. Consider this drawback if you expect your API to evolve over time.

Abstract Classes - key points
  • Any class with an abstract method is an abstract class.
  • You can't instantiate an abstract class, only its subclass(es).
  • A subclass of an abstract class can only be instantiated if it overrides each of the abstract methods of the superclass and provides an implementation for each of them. This guarantees that any subclass will have (hopefully valid and useful) implementations of each abstract method.
  • If an abstract class doesn't implement all of the superclass methods, then it is also abstract (and therefore can't be instantiated).
  • Static, private, and final methods cannot be abstract, since these kinds of methods can't be overridden by a subclass. But such methods can be class methods (concrete methods) of an abstract class.
  • An abstract class can have concrete methods.
  • It doesn't make sense for an abstract class to be static, since a static class can't be instantiated. If you only need one instance (the static class itself) then why make it abstract? But it could make a lot of sense for a subclass to be static. An example would be a static SteeringMotor class which extends the abstract Motor class.

Examples
Abstract Class
Interface
Here is an abstract class which defines a generic eeprom memory which is used in JCX tagging. This portion has one concrete method (the constructor) and two abstract methods.
abstract class Eeprom {



	/**integer represents the end of the systronix sacred area*/
private int endIndexSacred=-1; /**
* takes in a JCX address, note that any subclass MUST call super(int JCXaddress, SpiSlaveSelect JCXchip_select)
* and it must create a SpiSlaveDevice to attach to port
*/
public Eeprom(int JCXaddress, SpiSlaveSelect JCXchip_select)
{
baseAddr=JCXaddress;
cs=JCXchip_select;
endIndexSacred=-1;
} /**
* @return int the size of the eeprom in bytes
*/
abstract public int getEepromLength(); public abstract boolean blankCheck(); }
 
Here is a portion of one subclass which implements a driver for a specific eeprom (25LC160) used on JCX boards. This particular subclass is non-static, since each JCX I/O board contains tagging memory, so there is typically one instance of this eeprom per I/O board, with up to five I/O boards per JCX system.
class Jcx25LC160 extends Eeprom
{ /**
* number of bytes in EEPROM, 0 inclusive so 2047 means 2048 bytes
*/
public final int EEPROM_LENGTH = 2048; /**
* returns the size of the eeprom in bytes
* @return int
*/
public int getEepromLength()
{
return EEPROM_LENGTH;
} /**
* Determine if an eeprom is blank (contains all 0xFF)
* @return true if blank, false if not
*/
public boolean blankCheck()
{
int nonblank = 0;
int data;

for (int adr = 0; adr < EEPROM_LENGTH; adr ++)
{
try
{
data = read (adr);
if (0xff != data)
{
nonblank++;
System.out.println ("Nonblank @" + adr + ": 0x" + Integer.toHexString(data));
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}

if (nonblank > 0)
{
// for debug only
System.out.println (nonblank + " nonblank locations found; blank check fails!");
return false;
}
return true;
} }
 

Combining Interfaces and Abstract Classes
It's common and acceptable to mix these two, typically by creating an abstract class which implements an interface.
   

 
Systronix® 939 Edison St, Salt Lake City, Utah, USA 84111
Tel +1-801-534-1017, Fax +1-801-534-1019
contact us     Time Zone: MDT (UTC-6)
 

Java and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
Systronix is independent of Sun Microsystems, Inc.
TStik, JStik, JCX, JStamp, JSimm, JDroid, and JRealTime are trademarks of Systronix, Inc.
1-Wire, iButton and TINI are trademarks of Dallas Semiconductor
Simmstick is a trademark of Dontronics
LEGO® is a trademark of Lego A/S, Denmark