No more downcasting via “Recursive Bounds”
May 4th, 2008
I recently coded a fairly tiny application that made use of the MVC pattern. One of the things that I noticed while I was writing it was that I was down-casting a lot. Imagine something like this:
Example
// main type
interface Model {
void someMethod();
}
// implementation
class Mixer implements Model {
public void anotherMethod(){
System.out.println("hey");
}
public void someMethod() {
System.out.println("dude");
}
}
Now If I want to invoke both methods, I’d have to do something like this:
final Model m = new Mixer();
m.someMethod();
// downcasting .
// imagine this with more model objects
// with unique methods...
((Mixer)m).anotherMethod();
I am really annoyed about this whole downcasting. It does not make my code look that pretty. So I decided to use Generics; more in specific the recursive bounds idiom which was used in the implementation of the Java 5.0’s Enums.
The solution
interface SuperClass<S extends SuperClass<S>> {
S subclassInstance();
}
interface AnotherType {
void print();
}
The next step is to implement the previous interfaces. Something like this:
/**
* subclass A
*/
static
class SubClassA implements
SuperClass<SubClassA>,
AnotherType
{
private final String name;
SubClassA(){
final Random random = new Random(19580427);
name = getClass().getName()
+ random.nextInt();
}
public SubClassA subclassInstance(){
return this;
}
public void print(){
System.out.println(name);
}
}
/**
* subclass B
*/
static class SubClassB implements SuperClass<SubClassB>,
AnotherType
{
private final String name;
SubClassB(){
final Random random = new Random(19580427);
name = getClass().getName()
+ random.nextInt();
}
public SubClassB subclassInstance(){
return this;
}
public void print(){
System.out.println(name);
}
}
Then I can write code like this one and totally avoid dowcasting between objects:
public static void main(String... args){
final SubClassA sca = new SubClassA();
final SuperClass<SubClassA> sc = sca;
final SubClassA sca2 = sca.subclassInstance();
final SubClassA sca3 = sc.subclassInstance();
// no casting..cool huh!
sca2.print();
sca3.print();
}
And there you go… I’ve totally solved my downcasting problem!
Leave a Reply