Home > Computer, Java > Unimplementable Interface

Unimplementable Interface

November 14th, 2008 nawaman Leave a comment Go to comments

Java Interface

This article presents a technique used to create a Java interface that is usable by everyone but only implementable by classes in the same package.

Interface is a mechanism in Java programming language that enables mix-ins without using multiple inheritance. Interface is always composed of zero or more abstract public methods. A Java class can be defined to implement any interface that it has permission to. For example, a public interface can be used and implemented by any one and default interface can be used and implemented by any class in the package. This seems to be very natural and fit well for almost every case. However, there is some situation we may want a more flexible way. To better understand what this post is about, you first need to distinguish between using and implementing an interface.

To use an interface, like using a class, we declare variables or function return type or function parameters with the interface. For example:

Serializable Data = null;

To implement an interface, we define a class or an interface that implements or inherit the interface. For example:

public class MyClass implements Serializable {
	....
}

As mention above, in Java, if an interface can be used, it can be implemented. In other words, Java does not have a flexible way to allow one without another (at least directly). So how do you do if you need to create an interface that can be used but cannot be implemented. Let assume that you are building a canvas system that draw different kinds of spikes. First you create a class named Canvas for putting all spike into one picture. Spike must be an interface instead of a class in order to take advantage of mix-ins ability of interface. The code may looks something like this

public class Canvas {

	ArrayList Spikes = new ArrayList();

	public void addSpike(Spike pSpike) {
		this.Spikes.add(pSpike);
	}

	public void drawAll() {
		// Draw all spike
		for(Spike S : this.Spikes) {
			S.draw(this);
		}
	}

	// Package-internal function for the drawing actions.
	// Assume there are some reason you don't want these methods to
	//      be used in an uncontrollable fashion by others.
	void    drawLine()   { ... }
	void    drawThis()   { ... }
	void    drawThat()   { ... }
	Graphic getGraphic() { ... }
}

public interface Spike {
	public void draw(Canvas pCanvas);
}

Since Spike is responsible for drawing, it may mis-behave if any one can implement it. For example, a BadSpike below can stop the drawing process by putting itself in an infinite loop.

public class BadSpike {
	public void draw(Canvas pCanvas) {
		// Infinit loop
		while(true);
	}
}

You can provide different types of spikes that are sure to be well behave (and perhaps optimized). All of these are done in the same package with Canvas to allow access to internal function of Canvas. Some of these implementation can may allow customization by others (in a controllable way).

final public class Spike_Special1 {
	...
}

final public class Spike_Special2 {
	...
}

abstract public class Spike_Image {
	...
	abstract public void setImage(Image pImage);
	...
	final public void draw(Canvas pCanvas) {
		// Draw an image
		...
	}
	...
}

abstract public class Spike_Polygon {
	...
	protected List PolyGoneEntries = null;
	...
	final public void draw(Canvas pCanvas) {
		// Draw the polygon
		...
	}
	...
}

All the implementation above provides a controllable way to create customizable Spikes. However, it does not disallow others (from other package) to implement Spike. Which means that everyone can still implement BadSpike. (With a very long introduction), we now come to the point of this article, how to create an interface that can be used by every one but only implementable by some.

The solution is to use a local class as part of the interface signature. I call this method, Local Lock Pattern. First, a local lock class is created to be a package-private class. and use it in Spike.

// A package-private class that do completely nothing
class LocalLock {}

public interface Spike {

	public void draw(Canvas pCanvas);

	// Use a unlikely name to reduce a chagne of name conflicting
	public LocalLock __unlock__(LocalLock pLocalLock);
}

Then, all valid implementation of Spike must include the newly added method. For instance, Spike_Polygon may now look like this:

abstract public class Spike_Polygon {
	...
	protected List PolyGoneEntries = null;
	...
	final public void draw(Canvas pCanvas) {
		// Draw the polygon
		...
	}
	...
	// Use a unlikely name to reduce a chagne of name conflicting
	final public LocalLock __unlock__(LocalLock pLocalLock) { return pLocalLock; }	// Do nothing useful
	...
}

Since LocalLock is not visible outside the package, it is not possible to implement Spike outside the package since the implementing class must also implement __unlock__(…) method. The compiler will throw an error saying that LocalLock is not visible, therefore the implementation of __unlock__(…) is not valid.

Implementation of Spike’s valid subclass is possible since the method __unlock__(…) is already fully implemented. The interface Spike can also be used outside of the package, since using it does required the access to LocalLock.

NOTE: This solution may create a warning for exporting local API (LocalLock is local API that is exported by using it in a public method __unlock__(…)).

To conclude, this article present a simple technique for creating a Java interface that can be used by everyone but can only implemented by classes inside its package.

NawaMan

  1. Phoebe
    Phoebe
    November 16th, 2008 at 10:31 | #1

    Dropping by to read your blog.

  1. No trackbacks yet.