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

A

Arne Vajhøj

Richard said:
ArrayList.contains() and indexOf() seem to be go by just o/riding (equals()

Sure, but it happen that you want a natural equals in the class itself
and in some cases externally want to compare differently.

Arne
 
M

Mike Schilling

Arne said:
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.


That I don't understand.

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

All objects have hashCode.

Presumably you'd add Comparator.hashCode(object), which would
(logically) have to satisfy

compare(x,y) == 0 -> hashCode(x) == hashCode(y)

Then you could create a HashSet(Comparator c) that hashes the set's
members in a way that's compatible with the comparator's equals()
method.
 
R

Richard Maher

Hi Mark,

Mark Space said:
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:

Uhm. .Err. . If I only had one of them I probably wouldn't be trying to
stick them in a list :)
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.

So you're voting for the parallel list option?
Here's the Wikipedia article on Separation of Concerns.

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

I'm sure it's great; have you got a small example of it applying to this
case.
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.

Excellent! Now back to the behaviour of remove() methods on such objects in
an ArrayList. . .

Cheers Richard Maher
 
M

Mike Schilling

Peter said:
Since a List<E> implementation that allows for a custom equality
comparison is purely hypothetical (AFAIK), I suppose one could just
as
easily hypothesize a new interface ("Equator<T>" as Tom suggests, if
you're not worried about confusing cartographers :) )

I think that when it comes to naming the inventor of new APIs should
be given a certain amount of latitude.
 
R

Richard Maher

Hi Tom,

Tom Anderson said:
Can't be done. In java, by the time you have an instance, it's waaay too
late to add more attributes.

Ok, thanks.
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.

Just happy to learn off people who could know more than me.
I'm not sure what you mean by "o2.equals(E)",

This from JavaDocs ArrayList.remove()Removes a single instance of the specified element from this list, if it is
present (optional operation). More formally, removes an element e such that
(o==null ? e==null : o.equals(e)),
<<<<<<<<<<<<<<<

I'm just whining that in a perfect world it would say "e.equals(o)".
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));
}

As I said somewhere above, contains() and indexOf() seem to be fine by
overriding equals() and yes the others like remove() can be handled like: -
return things.remove(new ThingWithMinimumMessageNumber(thing)).

No one else seems to have a problem with it so I guess that's as good as it
gets?
// etc
}


Basically can't be done.

Certainly looks that way.
However ...

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

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

Good point, the SetMember can be done up front and there's also similar
stuff going on there. But seems like a fair bit of additional o/head to ask
JavaScript to getMember for each incoming message. Still, maybe it can be
moved down a bit and combined later with the first callback. Sounds
promising. . .

Nah, scrub that. The validation should be done in the Applet.
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

Cheers richard Maher
 
L

Lew

Richard said:
Random thoughts: - Keeping them in synch, redundant, extra o/head

That's "overhead", right?

Don't be afraid to spell it out - it's all right. At 30 words per minute, the
two characters you didn't type would have cost you less than one second, and
made your post more readable.
I don't know enough about HashMaps and HashTables (I'll read more today) but

There are a number of implementations of 'java.util.Map' in the standard API,
let alone third-party libraries. I'm not aware of any called 'HashTable'.
There is an old implementation, 'java.util.Hashtable', that you should eschew
in favor of 'java.util.HashMap'. 'Hashtable', besides having nearly all its
methods synchronized, sports the helper type 'Enumeration', which is something
like a lame 'Iterator' that lacks the fail-fast behavior of its 'Iterator'.
You're better off using 'HashMap' or another implementation, and wrap it in
'Collections.synchronizedMap()' if you need synchronized methods. There are
also 'Map' implementations in the 'java.util.concurrent' package for better
performance or more sophisticated locking in multi-threaded applications.
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?

Five minutes with the 'Map' Javadocs will answer that question for you. But
yes, as the Javadocs state, a 'Map' instance is an "object that maps keys to
values." And no, the keys do not have to be names.

Not all 'Map' implementations are named with the word part 'Hash'. Examples
include 'Attributes', 'AuthProvider', 'ConcurrentSkipListMap', 'EnumMap',
'Properties', 'RenderingHints' and 'TreeMap', just to name a few from the
standard API.

As to comparing 'List' to 'Map', that's a kind of apples-to-oranges
comparison. They have different purposes and characteristics.

You should know about maps. They are a fundamental data structure, and a
fundamental part of the collections API. If all you have in your toolbox is a
hammer, everything begins to look like a nail. It is not a good idea to delay
the acquisition of that knowledge.
 
L

Lew

Richard said:
I haven't heard that but I can see where they're coming from.

The Javadocs for 'java.lang.Object', the most fundamental Java class, say
about 'equals()', one of the most fundamental Java methods:
The equals method implements an equivalence relation on non-null
object references:
* It is reflexive: for any non-null reference value x,
x.equals(x) should return true.
* It is symmetric: for any non-null reference values x and y,
x.equals(y) should return true if and only if y.equals(x) returns true.
* It is transitive: for any non-null reference values x, y, and z,
if x.equals(y) returns true and y.equals(z) returns true,
then x.equals(z) should return true.
* It is consistent: for any non-null reference values x and y,
multiple invocations of x.equals(y) consistently return true
or consistently return false, provided no information used in equals
comparisons on the objects is modified.
* For any non-null reference value x, x.equals(null) should return false.

Anyway, it's pretty blatantly obvious that equality should be symmetric, don't
you think?
 
L

Lew

Richard said:
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();
}

Your 'if' and 'else' clauses really should be enclosed in braces.

Any time you see this kind of reflective checking of types (the 'instanceof'
tests), you can be pretty sure you have found a suboptimal solution that
object-oriented programming would have done better.

When you choose to use such a technique anyway, be aware of its shortcomings.
That doesn't mean don't use it, necessarily, but you will pay a technical
debt for it. For example, this 'equals()' is not symmetric. Under certain
circumstances, like comparing 'JSObject' and 'WindowSlot' instances in a
collection, this will require extra work to get right, and could depend on
third-party implementations that might change with new releases.

Don't get into the habit of that kind of programming.
 
L

Lew

Richard said:
Excellent! Now back to the behaviour of remove() methods on such objects in
an ArrayList. . .

Did you have a question about that?

The 'List#remove(int)' method "[r]emoves the element at the specified position
in this list".
<http://java.sun.com/javase/6/docs/api/java/util/List.html#remove(int)>

The 'List#remove(Object)' method "[r]emoves the first occurrence of the
specified element from this list, if it is present".
<http://java.sun.com/javase/6/docs/api/java/util/List.html#remove(java.lang.Object)>
(Note that the type of the argument is not 'E'.)

If you pull an iterator from the list, the 'Iterator#remove()' method
"[r]emoves from the underlying collection the last element returned by the
iterator".
<http://java.sun.com/javase/6/docs/api/java/util/Iterator.html#remove()>
 
L

Lew

Tom Anderson wrote ...
Richard said:
This from JavaDocs ArrayList.remove()
Removes a single instance of the specified element from this list, if it is
present (optional operation). More formally, removes an element e such that
(o==null ? e==null : o.equals(e)),

'E' and 'e' are not the same thing.
I'm just whining that in a perfect world it would say "e.equals(o)".

Which means exactly, precisely, completely the same exact, precise thing,
unless, of course, 'e == null', in which case your preferred form would be wrong.
 
L

Lew

Patricia said:
You appear to be assuming a symmetric implementation of equals. It
*should* be a safe assumption because the Object contract for equals
applies to all Java classes, and that contract requires symmetry.
However, I would not depend on it in this context.

Not so much assuming one as strongly recommending it. And it would still be
wrong to allow 'e.equals(o)' when 'e == null'.
 
M

Mike Schilling

Lew said:
Not so much assuming one as strongly recommending it. And it would
still be wrong to allow 'e.equals(o)' when 'e == null'.

I like what .NET does here. There's a static method on Object which
amounts to

public static equals(Object o1, Object o2)
{
if (o1 == null)
return o2 == null;
else
return o1.equals(o2);
}

(It's actually Equals, since .NET capitalizes method names, but that's
not important right now.)

I've had to write this logic often enough that I appreciate having it
already written and available everywhere.
 
T

Tom Anderson

I like what .NET does here. There's a static method on Object which
amounts to

public static equals(Object o1, Object o2)
{
if (o1 == null)
return o2 == null;
else
return o1.equals(o2);
}

+1 to this.

tom
 
T

Tom Anderson

I think that when it comes to naming the inventor of new APIs should
be given a certain amount of latitude.

As long as the name doesn't suggest the polar opposite of what the class
actually does.

tom
 
J

jrobinss

    public static equals(Object o1, Object o2)
    {
        if (o1 == null)
            return o2 == null;
        else
            return o1.equals(o2);
    }

(It's actually Equals, since .NET capitalizes method names, but that's
not important right now.)

I've had to write this logic often enough that I appreciate having it
already written and available everywhere.

I can't resist refering you to this discussion that I started some
time ago:
post-id: (e-mail address removed)
(Apr 11 2007, 5:13 pm)

You can see it via google here: http://tinyurl.com/dfn4ak

My personal conclusion, after much chatting from everyone about a lot
of things (the glory of usenet!), was...
These are the statistics (please restrain from laughing out loud :) )
. 262 classes
. 3 classes where it's useful. [...]
Which could mean that in this discussion everyone was right. :)
* Yes, beware of null pointers and manage them separately.
* But yes, it's sometimes useful to use my code (and since no one has
suggested better, I'll keep it as a static utility method in a
separate class).
 
A

Arne Vajhøj

Mike said:
Presumably you'd add Comparator.hashCode(object), which would
(logically) have to satisfy

compare(x,y) == 0 -> hashCode(x) == hashCode(y)

Then you could create a HashSet(Comparator c) that hashes the set's
members in a way that's compatible with the comparator's equals()
method.

That would explain it.

But it is rather common to want to be able to sort a list or
an array based on different properties - I would expect it to
be very rare to want to change the way objects are compared
for identity.

Arne
 
M

Mark Space

Mike said:
I like what .NET does here. There's a static method on Object which
amounts to

public class MyUtils {
public static boolean equals(Object o1, Object o2)
{
if (o1 == null)
return o2 == null;
else
return o1.equals(o2);
}
}

Then "import static MyUtils.*;" and you've got this everywhere, yes?

I'm not saying it wasn't clever to add this to Object, just that it
isn't hard to roll your own libraries of useful stuff either.
 
M

Mike Schilling

Mark said:
public class MyUtils {
public static boolean equals(Object o1, Object o2)
{
if (o1 == null)
return o2 == null;
else
return o1.equals(o2);
}
}

Then "import static MyUtils.*;" and you've got this everywhere, yes?

I'm not saying it wasn't clever to add this to Object, just that it
isn't hard to roll your own libraries of useful stuff either.

Very easy, as you point out. When you're working in a large team,
people tend to use the system classes when they can and roll their own
when they can't, and you often get N version of things like this, all
slightly different. So it's nice when they're in places like Object
where people will look first.
 

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,779
Messages
2,569,606
Members
45,239
Latest member
Alex Young

Latest Threads

Top