views:

37

answers:

1

I would love some help on a particular design. This is the code I wish worked:

abstract class Square {...}
abstract class Circle {...}

interface JPGExportable {...}

class SquareJPG extends Square implements JPGExportable {...}
class CircleJPG extends Circle implements JPGExportable {...}

interface Interface {
    draw(Square square);
    draw(Circle circle);
}

class Canvas implements Interface {
    draw(SquareJPG squarejpg) {...}
    draw(CircleJPG circlejpg) {...}
}

In words, Canvas should implement the specification that is Interface, BUT the draw-methods should only handle subclasses of Square and Circle that implement JPGExportable.

To my knowledge there are two solutions that work, but neither of which I think is very pretty:

/*
 * Using generics
 */
interface Interface<S extends Square, C extends Circle> {
    draw(S square);
    draw(C circle);
}

class Canvas implements Interface<SquareJPG, CircleJPG> {
    draw(SquareJPG squarejpg) {...}
    draw(CircleJPG circlejpg) {...}
}

/*
 * Using instanceof
 */
interface Interface {
    draw(S square);
    draw(C circle);
}

class Canvas implements Interface {
    draw(Square square) {
        if (square instanceof SquareJPG)
            // do stuff now
    }
    draw(Circle circle) {
        if (circle instanceof CircleJPG)
            // do stuff now
    }
}

In reality Square and Circle are fairly distinct, why a common super-class wouldn't be able to contain any common code. Also, a super-class implementing JPGExportable would feel... wrong; it's really a sub-feature.

An underlying reason why I don't like the generics-way is that I need to handle 7 different types. Perhaps I'm being picky, but 7 occurences of "T extends Type" in a row looks ugly.

  • Is there a third solution which looks better?
  • If not, which of the two "is better"?
+2  A: 

IMHO using generics is superior, since this way the compiler can give you some static type checking. In the second case you would find the bug during runtime.

It's difficult to find an alternative design without seeing the rest of your code. I.e. is it possible to draw any JPGExportable? Maybe you could have an interface with just one method draw(JPGEXportable)?

Grzenio
Thanks for the reply!No, JPGExportable does not imply drawable (that's probably what makes this a little harder). Therefore, an interface with draw(JPGExportable) would seem strange, and not really reflect what the interface is about.
Emore