cast to sub-class or extending instance of super or a.n.other

R

Richard Maher

Hi,

This is a probably a very simple OO question but (maybe 'cos I've been
deprived of alchohol for six weeks :) I can't think of the answer.

I have an instance O of class A and I want to add a couple of attributes to
it and store it in an ArrayList. I don't want to (and can't anyway)
reconstruct O by sub-classing A and the super(o.x,o.y) and the JRE won't let
me cast O to a sub-class of A (unless that was the original constructor
used)

At the moment I have a new class B that has variable instance of A and
instances of my other stuff, but in the ArrayList I only want to
remove(),contains() and so on, purely on the instance of A. I can override
the equals() and hashCode() methods in B to only check against A and ignore
the other stuff but ArrayList.mostMethods(o2) tend to use the o2.equals(E)
approach which isn't helpful.

As I said this has gotta be easier than this so please put me out of my
misery. What's the best way of "new O = instance of A + stuff. Then still
behave like A in Arrays/Collections) Or is there something more appropriate
than ArrayList?

Happy Easter!

Cheers Richard Maher
 
A

Arne Vajhøj

Richard said:
I have an instance O of class A and I want to add a couple of attributes to
it and store it in an ArrayList. I don't want to (and can't anyway)
reconstruct O by sub-classing A and the super(o.x,o.y) and the JRE won't let
me cast O to a sub-class of A (unless that was the original constructor
used)

At the moment I have a new class B that has variable instance of A and
instances of my other stuff, but in the ArrayList I only want to
remove(),contains() and so on, purely on the instance of A. I can override
the equals() and hashCode() methods in B to only check against A and ignore
the other stuff but ArrayList.mostMethods(o2) tend to use the o2.equals(E)
approach which isn't helpful.

As I said this has gotta be easier than this so please put me out of my
misery. What's the best way of "new O = instance of A + stuff. Then still
behave like A in Arrays/Collections) Or is there something more appropriate
than ArrayList?

You should be able to get it to work if you sub class.

But delegation will not work. Just because B delegates methods
to A does make it an A.

If A implements an interface then B could implement the same
interface and there may be some possibilities.

Arne
 
R

Roedy Green

What's the best way of "new O = instance of A + stuff.

You need what is called a copy constructor. e.g.

new Dalmatian( dog );

Unfortunately, Java has no easy way of composing one. You must
manually copy field by field in the constructor -- code that will stop
working if Dog acquires any more fields. I proposed Java invent copy
constructors, a bit like COBOL MOVE CORRESPONDING, but everyone shot
me down.

A new Dog ( dog ) takes a Dalmatian and strips it down. You do this
only to save space. A Dalmatian object will do anything a Dog object
does.

If you check out the code for the Replicator you will see constructors
that go back and forth from MiniZip to BigZip etc. BigZip is just a
MiniZip with extra fields.

see http://mindprod.com/products1.html#REPLICATOR

--
Roedy Green Canadian Mind Products
http://mindprod.com

"The most significant trend in the US industry has been the decline in the amount
of energy recovered compared to energy expended. In 1916, the ratio was about 28
to 1, a very handsome energy return. By 1985, the ratio had dropped to 2 to 1,
and it is still dropping."
~ Walter Youngquist, Professor of Geology

By 2003, it had dropped to 0.5 to 1 in the US, making oil extraction no longer economically viable, no matter how high the price of crude.
 
K

Kalessin

I dont suppose an anonymous inner class would work would it?

Dog mydog = new Dog() {
public bark() {
super.bark();
System.out.println("I can hear my dog barking!");
}
};

now when you call dog.bark(); on an array of dogs my dog will tell you it's
barking....but i can't remember how you
can access anonymous extra methods, since anonymous inner classes are
referred to like MyApp$1 (Anonymous class 1 declared in class MyApp)...
Hope This Helps
James Gardner
 
R

Richard Maher

Hi Peter,

Thanks for the reply.

Peter Duniho said:
[...]
As I said this has gotta be easier than this so please put me out of my
misery. What's the best way of "new O = instance of A + stuff. Then still
behave like A in Arrays/Collections) Or is there something more
appropriate
than ArrayList?

Hard to say without knowing exactly what you're trying to do.

Ok, cards on the table: - I have an instance of JSObject; I want to attach
an integer to it (oh, but we must know exactly what that integer does!)
Alright, it's a MinimumMessageNumber; any messages less than this will be
ignored. I want to reference the resultant object/structure by "index" for
performance. The ArrayList (I'm happy for alternatives and I'm looking at
your hashCode) will normally contain 1 element, and max-out at about10. The
minMsgNum is an appendage/baggage something that I'm sure there's a flash OO
term for like "orthogonal" that'll give everyone a boner (see, I've been
drinking :)
But,
typically in this sort of situation, you'd write a sub-class of A, and
then provide a constructor that creates a new instance given an instance
of A.

Please show me an example of a sub-class of JSObject that extends an
instance of JSObject.
This only works if you can replace your original A instance with a new
one, of course.
Ahah.

If you can't do that, then it seems to me that you're better off
maintaining a HashMap that uses your instance A as the key, and some other
class with the relevant properties as the value. You could optionally
refer to A in your property class, but the main thing would be that you'd
have to go through the HashMap any time you wanted to retrieve any
properties for an instance of A. Awkward, but it lets you store instances
of A in your ArrayList as-is, and yet still maintain extra properties for
each instance of A.

Sounds reasonable, but I have an index most of the time, is there no
collection or construct more appropriate?
I can't comment on whether storing your instances of A in a different data
structure would be more appropriate, because there's not much information
in your post as to how you're using the ArrayList. That said, it's
_possible_ you could forego the ArrayList altogether, and just use the
HashMap as I describe above.

I'll have another look at HashMap.
You can't sort a HashMap and you can't refer
to elements by index, but you can otherwise do collection-like stuff with
it.

I don't need to sort and i'm happy for remove() to reorganize the array.

But I just want to add an attribute to an object instance! Personally, I'm
glad that this is closer to rocket-science than I originally thought :) But
if I'm a vet and someone gives me a file that says "dog" and I want to
change it to Dalmatian, I can't/don't want to create a whole new file, I
just want to scribble in "Dog Type: Dalmation".

Is there something like an ArrayList where a AL.remove(o) et al does
e.equal(o) rather than o.equal(E)?

Cheers Richard Maher
 
R

Richard Maher

Hi Roedy,

Roedy Green said:
You need what is called a copy constructor. e.g.

new Dalmatian( dog );

Yep, that'd be good!
Unfortunately, Java has no easy way of composing one. You must
manually copy field by field in the constructor

If they're accessible in the forst place.
-- code that will stop
working if Dog acquires any more fields.

Quite possibly.
I proposed Java invent copy
constructors, a bit like COBOL MOVE CORRESPONDING, but everyone shot
me down.

Music to my ears!
A new Dog ( dog ) takes a Dalmatian and strips it down. You do this
only to save space. A Dalmatian object will do anything a Dog object
does.

If you check out the code for the Replicator you will see constructors
that go back and forth from MiniZip to BigZip etc. BigZip is just a
MiniZip with extra fields.

see http://mindprod.com/products1.html#REPLICATOR

--
Roedy Green Canadian Mind Products
http://mindprod.com

"The most significant trend in the US industry has been the decline in the amount
of energy recovered compared to energy expended. In 1916, the ratio was about 28
to 1, a very handsome energy return. By 1985, the ratio had dropped to 2 to 1,
and it is still dropping."
~ Walter Youngquist, Professor of Geology

By 2003, it had dropped to 0.5 to 1 in the US, making oil extraction no
longer economically viable, no matter how high the price of crude.

Cheers Richard Maher
 
T

Tom Anderson

I have an instance O of class A and I want to add a couple of attributes to
it

Can't be done. In java, by the time you have an instance, it's waaay too
late to add more attributes. In java, the set of attributes is defined
by the class, which is defined at compile-time; when you have an instance,
it's runtime, by which point the class definitions are set in stone.

Actually, you can define new classes at runtime, but it's a pain to do,
and anyway, you can't change the class of an object once it's made, so
that wouldn't help you anyway.

I'm guessing you have a backgrouns in a more dynamic language, like python
or javascript, where you can add fields willy-nilly.
At the moment I have a new class B that has variable instance of A and
instances of my other stuff, but in the ArrayList I only want to
remove(),contains() and so on, purely on the instance of A. I can
override the equals() and hashCode() methods in B to only check against
A and ignore the other stuff but ArrayList.mostMethods(o2) tend to use
the o2.equals(E) approach which isn't helpful.

I'm not sure what you mean by "o2.equals(E)", but this approach can
definitely be made to work, and is the java-esque way of doing it. If the
problem is that the list is calling methods on the object it contains
rather than the object you pass in, the solution is very simple - make
sure the object it contains is one of your objects too. That is, don't put
in Dogs and then try and remove Dalmatians, but make sure you always put
in Dalmatians (or whatever). So:

public class OriginalThing {}

public class ThingWithMinimumMessageNumber {
private OriginalThing thing;
private int minimumMessageNumber;

public ThingWithMinimumMessageNumber(OriginalThing thing, int minimumMessageNumber) {
this.thing = thing;
this.minimumMessageNumber = minimumMessageNumber;
}

public boolean equals(Object obj) {
if (!obj instanceof ThingWithMinimumMessageNumber) return false;
ThingWithMinimumMessageNumber that = (ThingWithMinimumMessageNumber)obj
return this.thing.equals(that.thing);
}
}

public class ThingManager {
private List<ThingWithMinimumMessageNumber> things;

public void put(OriginalThing thing, int minimumMessageNumber) {
things.add(new ThingWithMinimumMessageNumber(thing, minimumMessageNumber));
}
public boolean contains(OriginalThing thing) {
return things.contains(new ThingWithMinimumMessageNumber(thing, -1));
}
// etc
}
As I said this has gotta be easier than this so please put me out of my
misery. What's the best way of "new O = instance of A + stuff. Then
still behave like A in Arrays/Collections)

Basically can't be done.

However ...

You mention you're using JSObject. In that case, you can just do:

JSObject thing;
int minimumMessageNumber;
thing.setMember("minimumMessageNumber", new Integer(minimumMessageNumber));

In java terms, you haven't changed the set of attributes on the object.
But in javascript terms, you have. This might be enough for what you want
to do.

tom
 
L

Lew

Peter said:
AFAIK, Java doesn't include any collection types that allow you to
provide custom comparers or the like.

I must misunderstand what you mean, here. What about java.util.TreeSet?
TreeMap? Collections.sort()?
 
T

Tom Anderson

I must misunderstand what you mean, here. What about java.util.TreeSet?
TreeMap? Collections.sort()?

I assume by 'comparers or the like' Peter meant something like 'an object
which decides when two other objects are equal', with the emphasis on the
'equal'. I don't know what you'd call such a thing, but by analogy to
comparators, perhaps equators?

The idea being that it could decide that a EQUALS b in some sense even if
a.equals(b) or b.equals(a) was false, much as a comparator can decide a IS
GREATER THAN b even when a.compareTo(b) is zero or less, or doesn't exist.

tom
 
M

Mark Space

Richard said:
Ok, cards on the table: - I have an instance of JSObject; I want to attach
an integer to it (oh, but we must know exactly what that integer does!)
Alright, it's a MinimumMessageNumber; any messages less than this will be
ignored. I want to reference the resultant object/structure by "index" for
performance. The ArrayList (I'm happy for alternatives and I'm looking at
your hashCode) will normally contain 1 element, and max-out at about10. The
minMsgNum is an appendage/baggage something that I'm sure there's a flash OO
term for like "orthogonal" that'll give everyone a boner (see, I've been
drinking :)


This here strikes me as all kinds of wrongness. I'm not really sure
where the idea that a "property" must be added to an existing object
comes from. Given something like this, where JSObject is effectively a
global variable:

public class MyApplet extends JApplet {

private JSObject jso;
//...
}

I suppose the motivation might be to avoid more global variables.
However, that really doesn't make sense.

public class MyApplet extends JApplet {

private JSObject jso;
int minMessageNum;
Deque messageQueue;
//...
}

This works perfectly well.

In OO programming, there is the concept of "separation of concerns." In
other words, the JSObject is concerned only with accessing the browser
objects. It doesn't provide any other functionality because that would
just increase the cost of maintaining it. Likewise, the programmer who
uses a JSObject should avoid overloading a JSObject with a bunch of data
unrelated to the primary purpose of the JSObject. That data should go
in a separate object somewhere else.

Here's the Wikipedia article on Separation of Concerns.

<http://en.wikipedia.org/wiki/Separation_of_concerns>

I think Mike already hit the nail on the head when he said to create a
separate MessageObject, I'm just trying to show why it's a good idea and
why he's suggesting it.
 
M

Mike Schilling

Peter said:
For that matter, maybe there _is_ a List implementation out there
that
allows you to provide a Comparator. I haven't noticed one built
into
Java if there is, but it wouldn't be surprising if it exists
somewhere.


What job would a Comparator have in a List?
 
M

Mike Schilling

Arne said:
contains and indexOf using a logic different from the
objects equals.

I can see that, and I've sometime wanted it (though on a Set or a Map,
not a List.) Though, given that no List I know of has an index on
it, contains() and indexOf() are just loops that one could easily
write variants of.
 
A

Arne Vajhøj

Mike said:
I can see that, and I've sometime wanted it (though on a Set or a Map,
not a List.) Though, given that no List I know of has an index on
it, contains() and indexOf() are just loops that one could easily
write variants of.

Some prefer VW some prefer Toyota.

Arne
 
A

Arne Vajhøj

Peter said:
And lastIndexOf(Object o), remove(Object o), containsAll(Collection<?>
c), removeAll(Collection<?> c), and retainAll(Collection<?> c), not to
mention equals(Object o) and hashCode().

The fact is, as soon as you start introducing the concept of comparing
two objects (whether just for equality or a complete ordering), there is
also the possibility of wanting to provide custom logic for that
comparison. Given how many different operations are possible in a
List<E>, it seems perfectly logical to have a List<E> implementation
that allows for a custom Comparator.

Maybe overkill in many situations, but hardly unreasonable.

It is one of these things that are not necessary but could be
convenient.

And those things often get low priority in the Java world.
Interestingly, I just noticed that the Comparator<T> interface doesn't
include a hashCode() method. I guess they assume it will always be used
in a context where hash values aren't useful (e.g. a binary tree
implementation of a Map).

That I don't understand.

What should having hashCode() in Comparator<T> provide ?

All objects have hashCode.

Arne
 
R

Richard Maher

Hi Peter,

Peter Duniho said:
[...]
The
minMsgNum is an appendage/baggage something that I'm sure there's a
flash OO
term for like "orthogonal" that'll give everyone a boner (see, I've been
drinking :)

Has it been helping? :)

Seldom are [the correct] answers found in booze; but hey, there are none to
be found in milk either :)
[...]
If you can't do that, then it seems to me that you're better off
maintaining a HashMap that uses your instance A as the key, and some
other
class with the relevant properties as the value. [...]

Sounds reasonable, but I have an index most of the time, is there no
collection or construct more appropriate?

In what way?

AFAIK, Java doesn't include any collection types that allow you to provide
custom comparers or the like. But you certainly can wrap your A class in
a new class with the property, and then store the whole thing in a list.
Have the new class compare only on the composited A, and then when you
want to do a search on the list, construct a new wrapper class with the A
you want to search for.

Another alternative would be to keep a parallel ArrayList.

Random thoughts: - Keeping them in synch, redundant, extra o/head
This is
similar to using a HashMap, except you just use the index of your A
instance in the original ArrayList, as the index to look up your
property(ies) in the parallel ArrayList. The HashMap is IMHO conceptually
easier to code against, but if you wrapped all the A and property
management in a helper class, you could expose an API just as simple,
except using ArrayLists instead.

I don't know enough about HashMaps and HashTables (I'll read more today) but
I still like the look of ArrayLists, so I'm gonna stick with them a bit
longer. A guiding factor in the design is that by far and away the
biggest/most-often lookup hit is via "Index". Aren't HashThings more of a
key/value construct? Named/Valued pairs?

Yes I should've told you about the index requirement earlier :)
[...]
But I just want to add an attribute to an object instance! Personally,
I'm
glad that this is closer to rocket-science than I originally thought :)
But
if I'm a vet and someone gives me a file that says "dog" and I want to
change it to Dalmatian, I can't/don't want to create a whole new file, I
just want to scribble in "Dog Type: Dalmation".

Well, for better or worse, OOP languages aren't as messy as the real
world. Java in particular maintains tight control over objects, and you
can't just go scribbling on them any time you like. :p

The vet metaphor doesn't really do it for me anyway. A "dalmation" isn't
a sub-class of a "dog file". It's a sub-class of a "dog". And I doubt
there are many vets that organize their patient records by breed, where
they have one particular kind of file for Dalmations, another for Irish
Setters, etc. all files derived from a common "dog file" file. For that
matter, they probably don't even have separate kinds of files for cats,
dogs, birds, rabbits, etc.

Instead, they have a file that refers to a patient instance. The patient
instance itself is what maintains the breed information, and this is
entirely independent of the patient's file.
Is there something like an ArrayList where a AL.remove(o) et al does
e.equal(o) rather than o.equal(E)?

Not that I know of. Many people are of the opinion, with good
justification, that the equals() method should be symmetrical anyway.
That is, that it shouldn't matter whether you call e.equal(o) or
o.equal(e).

I haven't heard that but I can see where they're coming from.
That said, what's to stop you from just writing a helper method that does
the same thing the remove() method does, scanning the ArrayList until you
find the object you want, and then calling remove(int index) using the
index found from the scan?

Yeah, it's all doable. I just thought there was something "nicer".
If the only thing causing an issue here is the comparison used by
remove(Object o), it seems to me you can just avoid that altogether,
without much fuss. And if for some reason you are dealing with code
elsewhere that is calling remove() on your behalf, then just sub-class
ArrayList itself, and implement the behavior you want for remove(),
symmetric equals() method be damned! :)

Actually I gave you a red-herring about remove() - sorry. On second
thoughts, I'm not actually gonna call it but instead set the element to null
(which I believe is valid foe an ArrayList) when the JSObject goes away, and
possibly re-use the slot later. (I remembered I needed to preserve the
Indexe Values of the other Elements in the ArrayList)

Remove() was just an example of the "wrong/undesirable" equals() being
called. (Contains(), IndexOf() etc are all good!)

And for those methods that have issues I guess I can always remove(new
WindowSlot(myJSObject)) rather than remove(myJsobject). It just looks sooo
wrong.

I just wanted to make sure I wasn't missing some idylic Class or some
wiz-bang OO technique. Maybe nobody else every wants to add-value to an
already instantiated object for a while, but still have it behave/appear as
the original class?

Cheers Richard Maher
 
R

Richard Maher

Hi Mike,

Mike Schilling said:
Richard said:
Hi Peter,

Thanks for the reply.

Peter Duniho said:
On Sat, 11 Apr 2009 18:10:45 -0700, Richard Maher

[...]
As I said this has gotta be easier than this so please put me out
of my misery. What's the best way of "new O = instance of A +
stuff. Then still behave like A in Arrays/Collections) Or is there
something more appropriate
than ArrayList?

Hard to say without knowing exactly what you're trying to do.

Ok, cards on the table: - I have an instance of JSObject; I want to
attach an integer to it (oh, but we must know exactly what that
integer does!) Alright, it's a MinimumMessageNumber; any messages
less than this will be ignored. I want to reference the resultant
object/structure by "index" for performance. The ArrayList (I'm
happy
for alternatives and I'm looking at your hashCode) will normally
contain 1 element, and max-out at about10. The minMsgNum is an
appendage/baggage something that I'm sure there's a flash OO term
for
like "orthogonal" that'll give everyone a boner (see, I've been
drinking :)

Turn things around: create a MessageObject that contains two fields:

1. You minimum message number
2. A reference to your JSObject
MessageObject can also delegate some methods to the JSObject, if
that's convenient.

Make your ArrayList a List or MessageObjects.

If you need them sorted, use a TreeSet instead of an ArrayList and
define MessageObject.compareTo() appopriately.

That's where I got to so far (See below). I'm not totally happy with it for
reasons discussed previously with Peter.

Cheers Richard Maher


public class WindowSlot
{
public JSObject window;
public int minMsgNum;

WindowSlot(JSObject window)
{
this.window = window;
this.minMsgNum = getMsgSeqNum();
}

public JSObject getWindow() {
return this.window;
}

public int getMinMsg() {
return this.minMsgNum;
}

public boolean equals(Object o) {
if (o instanceof WindowSlot)
return window.equals(((WindowSlot)o).getWindow());
else
if (o instanceof JSObject)
return window.equals((JSObject)o);
else
return false;
}

public int hashCode() {
return window.hashCode();
}
}
 
R

Richard Maher

For that matter, maybe there _is_ a List implementation out there that
allows you to provide a Comparator. I haven't noticed one built into Java
if there is, but it wouldn't be surprising if it exists somewhere.

Good question :)

Cheers Richard Maher
 

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

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top