Hugh said:
I'm dealing with javax.microedition.lcdui.Graphics. It hasn't got a no-arg
constructor but bingo, does have an undocumented 2-arg constructor. I'm
going to give that a try with width, height as the args.
I've only just gotten comfortable with the idea that my source tree can
add to packages I don't own.
You can do this in some cases, but it is not generally a good idea. As
you found, sometimes you can't do it at all.
If I can get this to work, I can subclass
Graphics and just do logging on the calls I care about.
I see how I can do this once I can get to the constructor, but if there
were no available constructor would I still be SOL?
To subclass any class you need access to a constructor.
I've got to subclass
the Graphics class or my production code won't be able to write to it; and
any subclass is required to call super() in its constructors, isn't it?
If a constructor does not explicitly invoke a superclass constructor
then an invocation of super() is implicit.
And it has to be a subclass or my paint routines won't accept it as a
legitimate Graphics to write to.
It has to be a subclass of the class that the API uses. But that class
probably isn't javax.microedition.lcdui.Graphics -- it's probably a
superclass of that class. If it is, then it is certain that that class
has a protected constructor, or even a public one.
Remember that your subclass will not be doing anything directly -- it
can't, because it won't have anything of its own to paint _on_. It must
wrap a system-provided Graphics, as I described in my last message.
Here's a schematic example for a simple API to which the principle can
be applied:
package wb.acme.products;
import wb.Coyote;
public abstract class Anvil {
protected Anvil() {}
public squashCoyote(Coyote c) {}
}
==
package wb.acme.products.fy2004;
public class AnimatedAnvil {
AnimatedAnvil(int weight) {}
public squashCoyote(Coyote c) {}
public int getWeight() {}
}
==
package wb;
import wb.acme.products.Anvil;
public class RoadRunner {
Coyote hunter;
public void kickAnvil(Anvil a) {
a.squashCoyote(hunter);
}
}
===
Now suppose that an AcmeProductFactory provides a method that produces
Anvils. In fact, the runtime class of these objects is
wb.acme.products.fy2004.AnimatedAnvil in the current version of the
factory. Given an Anvil obtained in that way, you want to generate some
effect when its squashCoyote(Coyote) method is invoked (a log, a
fadeout, an epitaph...). You cannot subclass
wb.acme.products.fy2004.AnimatedAnvil, but you don't need to -- you only
need to subclass wb.acme.products.Anvil, like so:
package mypackage;
import wb.acme.products.Anvil;
import wb.Coyote;
public class AugmentedAnvil extends Anvil {
private final Anvil innerAnvil;
public AugmentedAnvil(Anvil a) {
innerAnvil = a;
}
public squashCoyote(Coyote c) {
innerAnvil.squashCoyote(c);
c.waveWhiteFlag();
}
}
Given you can then construct an AugmentedAnvil as a wrapper around the
AnimatedAnvil at hand (without even needing to know its actual runtime
class), and you can pass it around in place of the AnimatedAnvil it
contains. After it squashes a Coyote -- for which it will employ the
wrapped Anvil to do the real work -- it will cause that Coyote to wave a
white flag.
The same general programming idiom can very likely be applied to your
problem.
John Bollinger
(e-mail address removed)