interface fulfillment using fields - a java language proposition - part 2 of 2

Friday, July 11, 2008

I'm proposing a new keyword in Java class definitions, via. It essentially provides a methodology to simply and maintainably perform automatic delegation of interface methods to member fields. Part one introduced the concept, while part two will delve into more of the finer points.

Inheritance model integrity


The integrity of the inheritance model is maintained, as a class using via can also subclass another class, eg:
public class Laptop extends Computer implements Chargeable via this.internalBattery

And this class can even be subclassed itself:
public class MacBook extends Laptop

As seen in Part one, the classes compile to a traditional POJO so inheritance is not adversely affected. Of course any class can only extend one class, but
via can wrap many classes.

An illustration: If obj.method() is invoked and Obj uses via
  • an implementation of method() defined by Obj is looked for first.

  • If not found, then tries Obj.super.method() and so on up to Object.method() when not found.

  • If not found in the object's hierarchy up to and including Object then its implemented interfaces are searched (and the method invoked on the corresponding field).

  • If Obj's interfaces don't define it then work up the inheritance tree again, checking for any interfaces fulfilled with via.

  • In the situation where two or more interfaces are mapped with via in the same class and define the same method, obviously the JVM wouldn't know which field to invoke the method on. In this case a compiler error will be thrown. The solution is to explicitly override the method in Obj.


IOC and DI


What about the IOC pattern? As far as I see it, via is an awesome tool to use with IOC patterns, such as the Spring Framework. The idea with the IOC pattern (or Dependency Injection (DI)) is that any implementation class that fulfils the required interface can be swapped in at runtime. As far as I know DI can't be used to inject in a class to be subclassed, as the inheritance is defined as the subclassing of a given concrete class. As we saw in Part one, via basically lets us subclass interfaces. This means that a given interface can have our extra functionality or handling (using via), but that interface can be any class, it's just whatever the IOC container passes in. Very cool.


Multi-class interface fulfilment


Part one mentioned the idea of fulfilling an interface by the combining of two or more classes. The problem this is trying to solve is basically that to implement one interface method might require the help of a number of private methods. This then encourages splitting up interfaces so that the implementation classes don't suffer from unreadability and complexity. The problem this creates is that the exposed interfaces then increase in number and each is more basic than it need be.
The idea is that an interface can be defined with as many methods as the pure design requires, without concern about the resulting complexity of any implementors. Using via, a single class can implement an interface and define a number of implementation classes that combine to fulfil it. Here's a full example:
// first two package-visible interfaces
interface PackageIface1 {
void setName(String name);
}

interface PackageIface2 {
void setNumber(int number);
}

// now the public interface that combines them
public interface PublicIface extends PackageIface1, PackageIface2 {}

// the implemetation classes (package-visible)
class PackageClass1 implements PackageIface1 {
public void setName(String name) {...}
}

class PackageClass2 implements PackageIface2 {
public void setNumber(int number) {...}
}

// and the integration class that brings them all together
public class PublicClass implements PublicIface via this.pkgIface1Obj & this.pkgIface2Obj {
// class just defines the two fields and constructor(s)
}

(Note: The '&' symbol is arbitrarily chosen and could be anything that makes sense and is acheivable).
So the PublicIface is the only interface that needs to be exposed publicly. The PublicClass will be a fixed implementation to use. Discrete functionality subsets of PublicIface can be changed by swapping in a different implementation of PackageIface1 or PackageIface2 that get passed to PublicClass's constructor. And there is no limit to the number of classes that can be used to fulfil the main interface, provided that each one exclusively implements an interface that is extended by the main interface.


I may be way off track, but I dreamed this up when coming across the same problem for the tenth time in an enterprise Java project using Spring, and it just seems to fit. It may be that there are techniques or patterns out there that mean I can do all this already, or just that I should be slapped for suggesting such things. All feedback welcome.

posted 8:12 pm  

0 comments:

Post a Comment