"John C. Bollinger" <jobollin@indiana.edu> wrote in news:caafc5$fvf$1
@hood.uits.indiana.edu:
>> I'm having a really frustrating problem and I hope you guys can give me
>> some help.
[quoted text clipped - 9 lines]
> are most likely to run into) have protected no-arg constructors, at
> least in Java 1.4.
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. If I can get this to work, I can subclass
Graphics and just do logging on the calls I care about.
>> system passes in a Graphics class when it's time to update the screen, and
>> you can also create a graphics class through a static factory method
[quoted text clipped - 10 lines]
> this would be a perfect case for it, but as it is, you probably couldn't
> catch the system's manipulations of a Graphics -- only your own code's.
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? 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?
And it has to be a subclass or my paint routines won't accept it as a
legitimate Graphics to write to.
Hugh
Hugh Beyer - 11 Jun 2004 02:33 GMT
>>> I'm trying to write a test suite for a graphics-heavy app that uses
>>> MIDP/J2ME. These apps use the Graphics class to do their screen
[quoted text clipped - 16 lines]
> add to packages I don't own. If I can get this to work, I can subclass
> Graphics and just do logging on the calls I care about.
Argh. "Cannot create class in system package." So I can't use the constructor
unless I'm in the package and I can't be in the package, and without the
constructor I can't create a subclass.
Part of the problem is that since this has to run under the cellular device
emulator, I don't have much control over the environment.
Hugh
Liz - 11 Jun 2004 02:36 GMT
getInstance() ????
> >>> I'm trying to write a test suite for a graphics-heavy app that uses
> >>> MIDP/J2ME. These apps use the Graphics class to do their screen
[quoted text clipped - 25 lines]
>
> Hugh
Hugh Beyer - 11 Jun 2004 14:27 GMT
> getInstance() ????
>
[quoted text clipped - 26 lines]
>> Part of the problem is that since this has to run under the cellular
>> device emulator, I don't have much control over the environment.
Doesn't exist in the MIDP API.
Hugh
John C. Bollinger - 11 Jun 2004 15:17 GMT
> "John C. Bollinger" <jobollin@indiana.edu> wrote in news:caafc5$fvf$1
> @hood.uits.indiana.edu:
[quoted text clipped - 12 lines]
> 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.
>>You can subclass either class with an implementation that delegates to a
>>System-created Graphics instance, with logging wrapped around the method
[quoted text clipped - 5 lines]
> 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
jobollin@indiana.edu
Hugh Beyer - 11 Jun 2004 18:48 GMT
"John C. Bollinger" <jobollin@indiana.edu> wrote in news:cacet0$4uc$1
@hood.uits.indiana.edu:
>> And it has to be a subclass or my paint routines won't accept it as a
>> legitimate Graphics to write to.
[quoted text clipped - 9 lines]
> Here's a schematic example for a simple API to which the principle can
> be applied:
Way cool, and thanks for the example. I had been wondering about the
situation in which this pattern would be useful and that makes it clear.
Unfortunately, J2ME MIDP is way more restricted than you're thinking.
javax.microedition.lcdui.Graphics is a direct subclass of Object, and the
system passes it directly to a display's paint() method. So there's no
super/subclass relationship that I can exploit--my method either takes a
Graphics or it doesn't.
Arrgh very arrgh. But MIDP 2.0 lets me look at pixel values of an image--I'm
going to use the production paint() method to draw to a Graphics I created
using a factory, then draw by hand to another I create, then compare pixels.
It will be sensitive to the exact pixel location, which I don't love, but it
will let me test the basics.
Hugh
John C. Bollinger - 11 Jun 2004 22:22 GMT
> Unfortunately, J2ME MIDP is way more restricted than you're thinking.
Drat.
> javax.microedition.lcdui.Graphics is a direct subclass of Object, and the
> system passes it directly to a display's paint() method. So there's no
> super/subclass relationship that I can exploit--my method either takes a
> Graphics or it doesn't.
Bummer. I'm afraid I don't have any more ideas for you. I do find
myself thankful that I'm not currently working with J2ME, though. I
guess the API designers put an extreme premium on size, which is
understandable to some extent, but clearly the end product doesn't let
one do some of the things one sometimes wants to do.
John Bollinger
jobollin@indiana.edu
Hugh Beyer - 12 Jun 2004 00:57 GMT
"John C. Bollinger" <jobollin@indiana.edu> wrote in news:cad7q8$ean$1
@hood.uits.indiana.edu:
>> Unfortunately, J2ME MIDP is way more restricted than you're thinking.
>
[quoted text clipped - 10 lines]
> understandable to some extent, but clearly the end product doesn't let
> one do some of the things one sometimes wants to do.
I just went through the process of squeezing an app into the Nokia Series 40.
I was counting every class definition, every method, and every object, no
matter how trivial (especially the trivial ones). I ended up merging a bunch
of classes that started out distinct. They probably made the right trade-off.
Hugh
Dale King - 14 Jun 2004 08:54 GMT
Hello, Hugh Beyer !
You wrote:
> "John C. Bollinger" <jobollin@indiana.edu> wrote in news:caafc5$fvf$1
> @hood.uits.indiana.edu:
[quoted text clipped - 45 lines]
> And it has to be a subclass or my paint routines won't accept it as a
> legitimate Graphics to write to.
There is a more drastic route you can take, but it requires more
work on your part. Basically you can create your own wrapper API
for it. It would look something like this:
- Create an interface which contains the method signatures for
all of the methods in Graphics.
- Create an implementation of that interface that contains a
reference to an instance of the real lcdui.Graphics type that is
passed into the constructor. Its implementations of the interface
methods simply calls the corresponding methods on the
lcdui.Graphics instance.
- You can then overrid that class to add any functionality you
wanted to perform in the subclass you were trying to create.
- You rewrite mostof your application to work with the interface
instead of the lcdui.Graphics class. Since they have the same
methods that mostly involves changing a few variable types.
- For methods like paint that take the actual lcdui.Graphics
instance, you wrap that in the class you created above that adds
your additional functionlity and that is what the rest of your
code uses.
This is certainly a lot of work, but it is doable.

Signature
Dale King
My Blog: http://daleking.homedns.org/Blog