Java/OOP Question/Problem

D

DBloke

Hi,
I am fairly new to Java and OOP in general and I am using Java 5 at the
moment.

If a method expects a type of ImageFrame, which itself extends Frame
from awt, why will this method not allow me to pass my own JFrame
window, which inherits from Frame, I am using a cast (Frame) myJFrame,
but it keep throwing up an error about Frame not being an ImageFrame.

My understanding was that you could pass a Parent class as an argument
expecting a child of the parent class with a cast operation, I realise
this is not ideal but I do not have the source code to alter the class I
am trying to use, is there another way I can achieve this?

Thanks
DB
 
E

Eric Sosman

DBloke said:
Hi,
I am fairly new to Java and OOP in general and I am using Java 5 at the
moment.

If a method expects a type of ImageFrame, which itself extends Frame
from awt, why will this method not allow me to pass my own JFrame
window, which inherits from Frame, I am using a cast (Frame) myJFrame,
but it keep throwing up an error about Frame not being an ImageFrame.

Your wife says "Honey, I want a Poodle, which, as you
know, is a specific kind of Dog." So you go to the pet
store and buy a Schnauzer, which is also a specific kind
of Dog. Will your wife be satisfied?

The method says "I want an ImageFrame, which, as you
know, is a specific kind of Frame." So you go to the window
store and buy a JFrame, which is also a specific kind of Frame.
Will the method be satisfied?
My understanding was that you could pass a Parent class as an argument
expecting a child of the parent class with a cast operation, I realise
this is not ideal but I do not have the source code to alter the class I
am trying to use, is there another way I can achieve this?

"To achieve this ..." Well, it depends what you mean by
"this." If you mean "Make the method accept my JFrame even
though it's not an ImageFrame, as required," the answer is no:
You cannot do it. Your wife wants a Poodle and will not accept
a Schnauzer instead, even though both are Dogs.

But if you mean "Make the method accept my own extension
of ImageFrame," the answer is yes. Create your own BlokeFrame
class that extends ImageFrame, endow it with whatever methods
you like, and pass a BlokeFrame to the method. Since your
BlokeFrame *is* an ImageFrame, the method accepts it. Your
wife will be happy if you bring her a Miniature Poodle or a
Toy Poodle or a Standard Poodle; all are Poodles.
 
D

DBloke

Eric said:
Your wife says "Honey, I want a Poodle, which, as you
know, is a specific kind of Dog." So you go to the pet
store and buy a Schnauzer, which is also a specific kind
of Dog. Will your wife be satisfied?
Not true whatever she asks for and I giver her she is never satisfied :)
The method says "I want an ImageFrame, which, as you
know, is a specific kind of Frame." So you go to the window
store and buy a JFrame, which is also a specific kind of Frame.
Will the method be satisfied?

I am guessing not :)
"To achieve this ..." Well, it depends what you mean by
"this." If you mean "Make the method accept my JFrame even
though it's not an ImageFrame, as required," the answer is no:
You cannot do it. Your wife wants a Poodle and will not accept
a Schnauzer instead, even though both are Dogs.
Please understand even if I gave my wife the damned poodle she would
still not be satisfied :)
But if you mean "Make the method accept my own extension
of ImageFrame," the answer is yes. Create your own BlokeFrame
class that extends ImageFrame, endow it with whatever methods
you like, and pass a BlokeFrame to the method. Since your
BlokeFrame *is* an ImageFrame, the method accepts it. Your
wife will be happy if you bring her a Miniature Poodle or a
Toy Poodle or a Standard Poodle; all are Poodles.
She still wouldn't be satisfied with all or any of the above :)

Hmmm this was as I feared. It would have been better if the method took
an Interface or Frame reference, problem solved :), but this is not the
case :( is there a way I can make a Frame look like a JFrame? I tried
your way and it works as expected because of the is-a relationship, but
it looks fugly compared to the other windows, even playing with the
look-and-feel voodoo of AWT I want my new BlokeFrame to look like a nice
Windows XP Frame :) like all the other frames :p.

Thanks for your help anyway

DB
 
E

Eric Sosman

DBloke said:
[...]
Hmmm this was as I feared. It would have been better if the method took
an Interface or Frame reference, problem solved :), but this is not the
case :( is there a way I can make a Frame look like a JFrame? [...]

If by "look like" you mean "be" an ImageFrame, no: Java
will not let you just pretend that an actual thing is some
different kind of unrelated thing.

If by "look like" you mean "have the same on-screen
appearance," yes: You can re-invent all of JFrame inside
your own ImageFrame extension. It'll be a lot of work, though,
and I wouldn't recommend it.

Take a step back for a moment, and tell us about the
forest instead of the trees. What are you trying to do?
What is the larger problem you are trying to solve?
 
M

Mark Space

DBloke said:
Hmmm this was as I feared. It would have been better if the method took
an Interface or Frame reference, problem solved :), but this is not the
case :( is there a way I can make a Frame look like a JFrame? I tried

JFrames are Frames. A JFrame inherits directly from Frame and you can
pass a JFrame to any method that wants a Frame. You can also call any
Frame method on a JFrame yourself.

Although this doesn't mean the JFrame will do what you really want. I
don't have any real experience with AWT, just Swing, but I gather they
are pretty different. Unless what you are actually trying to do really
is "generic" with respect to Frames and JFrames, it may not work very well.

Note that you can make your own JFrame (class MyFrame extends JFrame {
.... }) and override any Frame methods to work better with your JFrame.
Just an idea....
 
S

Stefan Ram

DBloke said:
I am using a cast (Frame) myJFrame, but it keep throwing up an
error about Frame not being an ImageFrame.

Types of expressions are known at compile time, while
types of objects are known only at run time in the general case.

Let r be a reference-valued expression (syntactically, a
»UnaryExpressionNotPlusMinus«).

Let T be a reference type (syntactically, a »ReferenceType«).

Then

(T)r

is an expression, called a »cast expression« (»CastExpression«).

If the value of »r« is null, then the value of the cast
expression is the null reference cast to T.

Otherwise, the value of the expression r refers to an object.

Let O be the type of this object. (O is a class.)
Let R be the type of r.

A type »T« here is called a »supertype« of a type »S«
iff T is equal to S or
iff »S« directly or indirectly extends or implements T.

A reference expression can only be used to evaluate
to a reference value that refers an object if the type
of the reference expression is a supertype of the
type of the object.

Therefore, we require that in »(T)r«, T is a supertype of O
(the object refered to by the value of »r«).

If T is a supertype of R, this holds. Such a cast is called
an »upcast«.

If R is a supertype of T and not equal to T, then whether T
is a supertype of O in the general case can only be known
at runtime, because the type of O is only known at run time,
except that it is already known that it must be a subtype
of R. Such a cast is called a »downcast«.
 
D

DBloke

Eric said:
If by "look like" you mean "be" an ImageFrame, no: Java
will not let you just pretend that an actual thing is some
different kind of unrelated thing.
No I meant the second option :)
If by "look like" you mean "have the same on-screen
appearance," yes: You can re-invent all of JFrame inside
your own ImageFrame extension. It'll be a lot of work, though,
and I wouldn't recommend it.
Thanks so it s possible but will require a lot of effort ;) not ideal
but certainly a solution.
Take a step back for a moment, and tell us about the
forest instead of the trees. What are you trying to do?
What is the larger problem you are trying to solve?
I am trying to retrofit an Imaging API which uses only AWT and accepts
either AWT components or classes which inherit from AWT, I do not
understand enough about GIS and other geometric functions to write my
own library, so I hoped to use this one but I have zero to little
experience of AWT and only slightly more Swing.

The other dialogs in my application could easily be changed to AWT just
by dropping the J prefix to the components and frames.

My application extends a JFrame so is a JFrame is a Frame, and the
imaging library's imaging window is an ImageFrame which also is a Frame,
if this method had a Frame parameter I could pass either of these as an
argument as they are all types of Frames, but because it has an
ImageFrame parameter it will not work :(.

I think I have just seen another solution in this api, I could subclass
the drawing area and override the method which returns a reference to
the ImageFrame Window and return a Frame or JFrame instead, I can then
use my JFrame.

This method is protected so is begging to subclassed ;)

Thanks for all your help
DB
 
W

Wesley Mesquita

Hi,
I am fairly new to Java and OOP in general and I am using Java 5 at the
moment.

If a method expects a type of ImageFrame, which itself extends Frame
from awt, why will this method not allow me to pass my own JFrame
window, which inherits from Frame, I am using a cast (Frame) myJFrame,
but it keep throwing up an error about Frame not being an ImageFrame.

My understanding was that you could pass a Parent class as an argument
expecting a child of the parent class with a cast operation, I realise
this is not ideal but I do not have the source code to alter the class I
am trying to use, is there another way I can achieve this?

Thanks
DB

So think about the concept of extending a class, what is the reason to
do that? At least you will override the parent´s methods and in many
cases you will add new methods to those that the parent offered. If
you pass a parent class where it is expected a child, you are hurting
the "contract" since the parent problably don´t implement some methods
added to the child during the extending process.
 
D

DBloke

Stefan said:
Types of expressions are known at compile time, while
types of objects are known only at run time in the general case.

Let r be a reference-valued expression (syntactically, a
»UnaryExpressionNotPlusMinus«).

Let T be a reference type (syntactically, a »ReferenceType«).

Then

(T)r

is an expression, called a »cast expression« (»CastExpression«).

If the value of »r« is null, then the value of the cast
expression is the null reference cast to T.

Otherwise, the value of the expression r refers to an object.

Let O be the type of this object. (O is a class.)
Let R be the type of r.

A type »T« here is called a »supertype« of a type »S«
iff T is equal to S or
iff »S« directly or indirectly extends or implements T.

A reference expression can only be used to evaluate
to a reference value that refers an object if the type
of the reference expression is a supertype of the
type of the object.

Therefore, we require that in »(T)r«, T is a supertype of O
(the object refered to by the value of »r«).

If T is a supertype of R, this holds. Such a cast is called
an »upcast«.

If R is a supertype of T and not equal to T, then whether T
is a supertype of O in the general case can only be known
at runtime, because the type of O is only known at run time,
except that it is already known that it must be a subtype
of R. Such a cast is called a »downcast«.
Yes I do love Generics ;) but this api does not make use of this at all
afaics :(

I had hoped that even though ImageFrame is not an actual Frame it a
direct descendent of it and even though myImageFrame is not a Frame it
is still a descendent of Frame and only a level lower in the hierarchy
tree than ImageFrame I could still pass myImageFrame cast as a Frame but
it is not having any of it :)

Thanks anyway
DB
 
D

DBloke

Wesley said:
So think about the concept of extending a class, what is the reason to
do that? At least you will override the parent´s methods and in many
cases you will add new methods to those that the parent offered. If
you pass a parent class where it is expected a child, you are hurting
the "contract" since the parent problably don´t implement some methods
added to the child during the extending process.

Hmmm yes I understand this and of course it does make sense I guess <sigh>

I wish there were an option in the compiler which says I want to do
dangerous things like my great uncle C and I am prepared to accept
responsibility for my insane actions if I blow up the JVM, but please
trust me when I say I want to be a child for a few nanoseconds as
parenting is boring sometimes ;)

DB
 
L

Lew

DBloke said:
My application extends a JFrame so is a JFrame is a Frame, and the
imaging library's imaging window is an ImageFrame which also is a Frame,
if this method had a Frame parameter I could pass either of these as an
argument as they are all types of Frames, but because it has an
ImageFrame parameter it will not work :(.

I think I have just seen another solution in this api, I could subclass
the drawing area and override the method which returns a reference to
the ImageFrame Window and return a Frame or JFrame instead, I can then
use my JFrame.

This method is protected so is begging to subclassed ;)

Eric has already explained that you can't downcast something to a type that it
isn't. The run-time type must support the downcast.

Additionally, it is risky or broken to mix AWT and Swing components.
 
L

Lew

DBloke said:
Yes I do love Generics ;) but this api does not make use of this at all
afaics :(

Neither did the explanation to which you replied. Why did you mention
generics? Stefan didn't.
 
G

GArlington

Hi,
I am fairly new to Java and OOP in general and I am using Java 5 at the
moment.

If a method expects a type of ImageFrame, which itself extends Frame
from awt, why will this method not allow me to pass my own JFrame
window, which inherits from Frame, I am using a cast (Frame) myJFrame,
but it keep throwing up an error about Frame not being an ImageFrame.

My understanding was that you could pass a Parent class as an argument
expecting a child of the parent class with a cast operation,

This is NOT true: you can always downcast (i.e. child [subclass] to
parent [superclass]), but you have to provide a separate constructor
in your subclass to accept superclass as param and create a subclass
from superclass in order to be able to cast to child [subclass].
 
D

Daniel Pitts

GArlington said:
Hi,
I am fairly new to Java and OOP in general and I am using Java 5 at the
moment.

If a method expects a type of ImageFrame, which itself extends Frame
from awt, why will this method not allow me to pass my own JFrame
window, which inherits from Frame, I am using a cast (Frame) myJFrame,
but it keep throwing up an error about Frame not being an ImageFrame.

My understanding was that you could pass a Parent class as an argument
expecting a child of the parent class with a cast operation,

This is NOT true: you can always downcast (i.e. child [subclass] to
parent [superclass]), but you have to provide a separate constructor
in your subclass to accept superclass as param and create a subclass
from superclass in order to be able to cast to child [subclass].
WTF are you talking about?
Casting has absolutely nothing to do with constructors, only run-time
type and compile-time type.

At compile-time, you can cast to any subclass of the compile-time type
of the reference, or to *any* interface. At run-time, if the referenced
object's runtime-type doesn't match your cast, you'll end up with a
ClassCastException.
 
L

Lew

GArlington said:
This is NOT true: you can always downcast (i.e. child [subclass] to

"Downcasting" in Java refers to casting from parent to child. "Upcasting" is
child to parent.
parent [superclass]), but you have to provide a separate constructor
in your subclass to accept superclass as param and create a subclass
from superclass in order to be able to cast to child [subclass].

That is not at all true, or even sensible.

Stefan Ram explained it in detail in his post upthread.

You can downcast from a variable type to any subclass of that type provided
that the object actually is of that subclass type at runtime. No special
constructor needed. For example:

Writer wr = new FileWriter( file );
// widening conversion, i.e., upcast - no cast operator

FileWriter fw = (FileWriter) wr;

Legal even though FileWriter contains no constructor that accepts a Writer nor
any that accepts a subtype of Writer.
<http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.6>
 
D

DBloke

Neither did the explanation to which you replied. Why did you mention
generics? Stefan didn't.
Sorry it was late for me last night trying to figure this problem and
reading the posts, I saw T and wrongly associated this with a reference
to Generics <T>, It is a good explanation, but not the one I wanted to
hear :( I understand why this restriction applies I need to make square
pegs fit in round holes.

On the one hand I have an ImageFrame extending from AWT Frame, this is
the frame the API provides for its use, but it is AWT and on windows it
is fugly!!

On the other hand I have my nice ImageWindow which extends JFrame and
JFrame extends Frame, this looks better in windows than the fugly awt Frame.

At the end of the day they all descend from Frame there frame directly
mine indirectly via JFrame,

There is a method in this api which takes an ImageFrame argument when I
cast my ImageWindow to a Frame it says ok no probs, and I pass to this
method asking for an ImageFrame and it says ok, it compiles, but when I
execute it I get the ClassCastException, which I am not surprised about,
because in the method that takes the argument calls a method specific
to an ImageFrame but not a Frame.

I believe there is a reinterpret_cast which would do the job if I were
using C++ but I am not I am using Java :).

I thought I had found another way but overriding the method of interest
still insists I return an ImageWindow, is there any way in java to
override a method and change it's return type? countless searches
suggest not, but I believe there are some languages which use something
called reintroduce and I am also guessing nothing like this exists in
Java right ?
 
L

Lew

DBloke said:
There is a method in this api which takes an ImageFrame argument when I
cast my ImageWindow to a Frame it says ok no probs, and I pass to this
method asking for an ImageFrame and it says ok, it compiles, but when I
execute it I get the ClassCastException, which I am not surprised about,
because in the method that takes the argument calls a method specific
to an ImageFrame but not a Frame.

I believe there is a reinterpret_cast which would do the job if I were
using C++ but I am not I am using Java :).

This is eminently doable, actually, if you get the Java idioms just so.

You don't actually need to explicitly cast an ImageFrame to a Frame because it
already /is-a/ Frame. So any method that takes a Frame argument will accept
an instance of a subclass.

The converse, passing a Frame to a method asking for an ImageFrame, requires
an explicit downcast, and the object passed in had better actually *be* an
ImageFrame or the cast will fail.

If you got a ClassCastException passing a Frame into a method asking for an
ImageFrame, you must have done an explicit cast, and the Frame object at
runtime must not have been an ImageFrame in real life.

Compile-time type safety is designed to avoid that sort of thing, but it isn't
always available. For example, many Swing methods need a Graphics2D object
but are passed a Graphics object in the parameter list. So inside the method,
they have to do a cast on the parameter, call it 'g':

Graphics2D g2 = (Graphics2D) g;

If 'g' happens at runtime not to actually be a Graphics2D object, the cast
will fail.

Consider method in a class 'Eg':
public foo( ImageFrame imgF ) { ... }

Now you have some other class instance that wants to pass it a Frame:

Eg e = new Eg();
Frame f = acquireFrameSomehow();
e.foo( f );

That should not compile.
This will compile:

e.foo( (ImageFrame) f );

If the 'f' acquired was not actually an ImageFrame, this call will fail at
runtime with a ClassCastException.

You haven't shown us your code, so I can only guess about it, and speak from
general principles.
 
R

Roedy Green

Your wife says "Honey, I want a Poodle, which, as you
know, is a specific kind of Dog." So you go to the pet
store and buy a Schnauzer, which is also a specific kind
of Dog. Will your wife be satisfied?

I love your explanation. I found these dog breed analogies make Java
classes absurdly simple.
 
E

Eric Sosman

Roedy said:
I love your explanation. I found these dog breed analogies make Java
classes absurdly simple.

Credit where it's due: I've seen *your* explanations of
class relationships by analogy with dog breeds and found
them a good model to follow. Arf! Wau!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,989
Messages
2,570,207
Members
46,785
Latest member
undedgini

Latest Threads

Top