Java type-casting -- Q3

L

Lew

grz01 said:
First, I suggest you simply stop reading my postings if they make you
so upset -- no good for your health... :)

How do you read that I'm upset? I'm not upset. I merely pointed out that
you've been repeating your same questions and complaints in post after post
without much evidence that you have taken the advice or free code that has
been offered, and beyond that, engaging point by point in the lively and
interesting discussion that you introduced.
Second, from what I can see, what they call "polymorphism" in Java, is
something totally different from polymorphism in the functional
languages that I have been working with (Haskell, ML, etc).

Here's what I mean by "(type) polymorphism" in computer science:
<http://en.wikipedia.org/wiki/Polymorphism_(computer_science)>

Java features certainly fulfill the definitions in that article, for both
"ad-hoc polymorphism" and "parametric polymorphism". In fact, it even points
out that "Java, C#, Visual Basic .NET and Delphi (CodeGear) have each recently
introduced 'generics' for parametric polymorphism." Needless to say, Java has
had ad-hoc polymorphism from the get-go.

Naturally the expression of polymorphism will differ between a functional
language and an object-oriented language. Of course.

You have to step back and look at the definition of the term, and by that
meterstick Java certainly features polymorphism.
 
G

grz01

*Do not use wildcard types as return types.* [emphasis original]
Rather than providing additional flexibility for your users,
it would force them to use wildcard types in client code.

Thank you, Lew.
Definitely a point to keep in mind for the future.

/ grz01
 
L

Lew

Here's what I mean by "(type) polymorphism" in computer science:
<http://en.wikipedia.org/wiki/Polymorphism_(computer_science)>

Java features certainly fulfill the definitions in that article, for
both "ad-hoc polymorphism" and "parametric polymorphism". In fact, it
even points out that "Java, C#, Visual Basic .NET and Delphi (CodeGear)
have each recently introduced 'generics' for parametric polymorphism."
Needless to say, Java has had ad-hoc polymorphism from the get-go.

Naturally the expression of polymorphism will differ between a
functional language and an object-oriented language. Of course.

You have to step back and look at the definition of the term, and by
that meterstick Java certainly features polymorphism.

I think the difference you've seen may be between polymorphism as we discussed
above and
<http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming>

This confused me as well. I should have dug a little more into Wikipedia first.

You are right, when people refer to "polymorphism" in Java and object-oriented
languages generally, they aren't referring to the exact same thing as we've
been discussing.

I was wrong in my understanding of what the Wikipedia article meant by "ad-hoc
polymorphism". I thought at first that this was related to instance method
overriding, but actually it's about method overloads if anything.

Sorry for any confusion I've increased.
 
G

grz01

without much evidence that you have taken the advice or free code that has
been offered...

Ok, I just wasnt totally content with the advices, so far.
Neither was I asking for free code, but rather looking for insights or
knowledge that I might have missed.
Java features certainly fulfill the definitions in that article, for both
"ad-hoc polymorphism" and "parametric polymorphism".  In fact, it even points
out that "Java, C#, Visual Basic .NET and Delphi (CodeGear) have each recently
introduced 'generics' for parametric polymorphism."

OK, so I guess I should correct myself:

...And I also now start to suspect that "generics" is
kind of a "poor man's solution to *parametric* polymorphism".

/ grz01
 
L

Lew

OK, so I guess I should correct myself:

...And I also now start to suspect that "generics" is
kind of a "poor man's solution to *parametric* polymorphism".

Java generics *is* parametric polymorphism. You cannot expect these things to
look the same in an object-oriented language as in a functional language. The
way generics works in Java is appropriate to the style of Java as a language,
it isn't a "poor man's" anything.

If you tried to apply the ML way to Java, for example, then you'd find out
what a "poor man's solution" is. My point is that generics fulfills the
definition and purpose of parametric polymorphism.

It also goes farther than mere polymorphism. In the context of Java as an
object-oriented language, generics allows one to declare type relationships
between methods and structures, in effect comprising a theorem language for
types. Properly used, generics allows one to lock down type safety in a very
powerful and helpful way.

Perhaps you should consider not trying to force the square peg of Java into
the round hole of functional programming, but take it for what it is and use
the incredible power that confers on you.
 
G

grz01

Lew wrote:
Java generics *is* parametric polymorphism.

Mmm... ok... let me try to correct myself again :)

...And I also now start to suspect that "generics" is
kind of a "poor man's solution to type-polymorphism in computer
science".

And one thing I know, is that
type-polymorphism without the concept of tuples
is a very poor kind of polymorphism.
Perhaps you should consider not trying to force the square peg of Java into
the round hole of functional programming, but take it for what it is and use
the incredible power that confers on you.

Mmm... maybe so... maybe so...

:)
 
G

grz01

If you mean literally a single type that allows for a variable length type  
parameter list, that's definitely more problematic.  It would require a  
significant enhancement to a variety of pieces of Java, and I would be  
surprised if you ever would see that amount of work applied to the problem.

Yes, thats what I meant.

Would be interesting, though, to see some concrete example of how that
would cause a significant problem, and affect things already existing
in the language... guess I would need to sketch some code-examples
myself, to see what the problems are...

/ grz01
 
M

markspace

grz01 said:
2) writing their individual and mutually
incompatible, almost identical versions of
my.useful.goodies.package.Pair<A,B>
or
my.other.goodies.package.Triple<A,B,C>


Seriously, aside from the example that I just wrote for you, never.
I've always defined a type that had some other meaning besides "I'm
holding these types for someone else."

For example the last "pair" I designed was for a time keeping
application. I had two longs, and I needed to determine how much time
existed between them. I didn't use an array or a generic "Pair", I made
a class called "Interval" and put the start time and end time in that.
Simple, easy, and described the problem space almost intuitively.

I think the problem is that you've spent too much time with your
favorite functional programming style, and haven't stopped to consider
that it may not be the best. So far we haven't got an SSCCE out of you
yet. Nor have we got a practical example why you want to return some
number of dissimilar types in an anonymous way. It's just a problem
that doesn't come up. Once you actually analyze a problem, then you can
correctly design the classes you need for it. "A list of a bunch of
different stuff" is hardly ever a reasoned solution.
 
M

markspace

grz01 said:
And I also now start to suspect that "generics" is
kind of a "poor man's solution to polymorphism"


I mentioned this in a previous post, but maybe you missed it.

Generics in Java are *not* polymorphic. They aren't designed to be.
They're something else. Arguably, generics are better than
polymorphism, because they prevent you from doing broken things with
types. But I don't think most folks have adjusted their thinking in
that direction yet.

Some people can adapted to new things. Some have to make do with old
things. So it goes.
 
L

Lew

I mentioned this in a previous post, but maybe you missed it.

Generics in Java are *not* polymorphic. They aren't designed to be.

Yes, they are.

It's important to note that the OP does not mean the same kind of polymorphism
that you do here. He means "type-polymorphism" and we mean
"object-polymorphism". The former is what we mean by "parameterized types".
The latter is "polymorphism" in the sense that Grady Booch defined in his
seminal works on object-oriented programming.
They're something else. Arguably, generics are better than
polymorphism, because they prevent you from doing broken things with
types. But I don't think most folks have adjusted their thinking in
that direction yet.

Generics are not a substitute for (object-) polymorphism, so it's meaningless
to say they're "better" than (object-) polymorphism. (Unless the context
changes, I'll just say "polymorphism" for the object-oriented one now.)
That's like saying "static access is better than methods". You are correct
that generics can lock out broken things with types, but they don't stop the
programmer from doing broken things with types through the abuse of generics.

Generics in Java are a kind of type calculus. They embody a set of
declarations and constraints about type relationships in a program, so that
the programmer can prove at compile time that certain type relationships and
constraints will pertain at run time without fear of ClassCastExceptions and
the like. In a way they're like compile-time assertions, only about types
rather than program state.

There are definitely subtype relationships one can express in generics,
through the use of bounded wildcards.

Note further that there is nothing in the use of generics that eliminates the
need for or value of polymorphism, and actually generics are a part of the
polymorphism mechanism.

Consider the 'Comparable<T>' interface. An implementing class such as
'String' polymorphically (in both senses) invokes its 'compareTo(T o )' method
as 'compareTo( String o )' (before erasure). Object polymorphism ensures
dispatch to the 'String#compareTo' method, and type polymorphism ensures that
the argument is a 'String'.

For a deeper example, that is, more deeply polymorphic, consider the hierarchy
from 'java.util.Stack<E>' on up to 'java.util.AbstractList<E>' and beyond,
including to 'java.util.List<E>'. You can declare a variable

Vector <Foo> foos = new Stack <Foo> ();

If you call 'foos.firstElement()' you will polymorphically (in both senses)
call 'Stack<E>#firstElement()' and if it isn't 'null', obtain an instance of
'Foo'.

To show that generics are object-polymorphic:

public class Quisp <E extends Comparable<? super E>>
{
Vector <E> stuff = new Stack <E> ();

// constructors, initialization, populate stuff

public E findLessThan( E query )
{
for( Enumeration <E> nume = stuff.elements();
nume.hasMoreElements(); )
{
E compar = nume.nextElement();
if ( compar.compareTo( query ) < 0 )
{
return compar;
}
}
return null;
}
}

Here we see an example of object-polymorphism on the parameterized type 'E'.
 
M

markspace

grz01 said:
Or even better, define a general type like
java.lang.Tuple<T1, ..., Tn>


Type-safe heterogeneous containers: Effective Java, Joshua Bloch. I
just whipped this up, it's untested ('cept for the short static method
at the end).

Note: I've never needed to use one of these either.



import java.util.HashMap;
import java.util.Map;



/** A type safe heterogeneous container.
*
* @author Brenden
*/
public class HeterogeneousContainer {

Map<String,Class<?>> namesAndTypes;
Map<String,Object> values;

public HeterogeneousContainer( Map<String, Class<?>> namesAndTypes )
{
this.namesAndTypes = new HashMap<String,Class<?>>( namesAndTypes );
values = new HashMap<String,Object>( namesAndTypes.size() );
}

public <T> T get( String name, Class<T> type ) {
if( type == namesAndTypes.get( name ) ) {
return (T) values.get( name );
}
else {
throw new IllegalArgumentException( "Pair (" + name + ", "+
type+") do not exist." );
}
}

public <T> T put( String name, Class<T> type, T value ) {
if( type == namesAndTypes.get( name ) ) {
return (T) values.put( name, value );
}
else {
throw new IllegalArgumentException( "Pair (" + name + ", "+
type+") do not exist." );
}
}

public static void main( String[] args )
{
HashMap<String,Class<?>> namesAndTypes = new
HashMap<String,Class<?>>();
namesAndTypes.put( "first", String.class );
namesAndTypes.put( "second", Integer.class );
HeterogeneousContainer test = new HeterogeneousContainer(
namesAndTypes );
test.put( "first", String.class, "A String");
test.put( "second", Integer.class, 4 );
String s = test.get( "first", String.class );
Integer i = test.get( "second", Integer.class );
System.out.println( "Values: " + s + i );
}
}
 
G

grz01

Very unusual, as far as I know.  If you have data to the contrary, I'm all  
ears.  Even your own example is not one of "defining a function that  
returns two or more different things of different types".  Rather, you  
want a function that returns a single collection of grouped objects.

I really dont get what you aim at here?
You can look at it either way, I guess,
but a Pair seems like the more general
and simpler abstraction to me.
I've never defined a silly class for holding two or more values.  When I  
define a class for holding two or more values, it's always a non-silly  
class.



I never have.  I doubt many other programmers have either.

OK, I then doubt you're too familiar with the principles of
"dont repeat yourself" and being a "lazy programmer".

http://en.wikipedia.org/wiki/Don't_repeat_yourself
http://blogoscoped.com/archive/2005-08-24-n14.html

Regardsless of programming language,
and in my experience, I think these are extremely
valuable principles.

But since they are probably also in the field
of "religious issues", I think I will not try
any further to convince you :)

/ grz01
 
G

grz01

First of all, Java doesn't have call-by-reference.  It _only_ supports  
call-by-value.  

Yes, technically, you are right, of course.
I should have said something like
"the reference-semantic of the Objects implementation in Java,
and how it pertains to method-parameters"
instead.

I did "cut a corner" there, sorry.
 
L

Lew

grz01 said:
OK, I then doubt you're too familiar with the principles of
"dont repeat yourself" and being a "lazy programmer".

http://en.wikipedia.org/wiki/Don't_repeat_yourself
http://blogoscoped.com/archive/2005-08-24-n14.html

Regardsless of programming language,
and in my experience, I think these are extremely
valuable principles.

But since they are probably also in the field
of "religious issues", I think I will not try
any further to convince you :)

They aren't religious issues. They're buzzwords for two of the toolshedful of
design and development principles. Turning them into religious issues is one
of the surest ways of ruining their utility.

"Don't repeat yourself" (DRY) isn't the same as "Don't ever, ever, ever repeat
yourself under pain of eternal Hell fire!"

Being a lazy programmer doesn't mean expending less energy than you need to.

These are principles that must be applied intelligently and in balance with
other principles of intelligent, competent programming. Just because you are
championing 'Pair' doesn't mean it was the right choice for Peter's scenarios,
nor that his decision not to implement 'Pair' was made in violation or
ignorance of the principles. The rhetorical device of labeling Peter
deficient (/ad hominem/ fallacy) because he disagreed with your point is
illogical and has failed.

What Peter described was neither repetition of code idioms nor expenditure of
excess energy, so I don't know why you picked those two principles in
particular. He pointed out that the simplistic nature of the proposed
'Pair<T,U>' class was insufficient for the needs he has encountered. That
means that the needs were unique and he was not repeating code. It also means
that he would have had to expend more effort to make 'Pair' suit his purpose,
so the principle of lazy programming that you endorsed pushed him away from
that choice.

Instead of attacking the person who disagreed with you, learn from his wisdom.
 
G

grz01

Im sure you did...

But, in trivial cases like this, why exactly is that Interval
class a better solution than using Pair<Date, Date> or something?
Which is, at least, just a simple and easy.

Plus saves you from bloating your code with yet another
<flame-warning>silly</flame-warning> JavaBean class :)

If the Interval type is part of an API - yes - Interval
is probably the better choice.

But for all the internal logic of a class or library, etc,
where these "one-off" things keep popping up daily...?

I say, Dont Repeat Yourself.

And, after all those years, Im afraid,
I'll probably keep saying that until the end of days :)

/ grz01
 
G

grz01

You're not nearly lazy enough if you're willing to write code that you  
have to puzzle over later to figure out its structure.

Pete

Well, the day I need to sit "puzzle" over the type Pair<A,B>
its probably time to retire :)

/grz01
 
G

grz01

grz01 said:
Or even better, define a general type like
java.lang.Tuple<T1, ..., Tn>

Type-safe heterogeneous containers: Effective Java, Joshua Bloch.  I
just whipped this up, it's untested ('cept for the short static method
at the end).

Note: I've never needed to use one of these either.

import java.util.HashMap;
import java.util.Map;

/** A type safe heterogeneous  container.
  *
  * @author Brenden
  */
public class HeterogeneousContainer {

     Map<String,Class<?>> namesAndTypes;
     Map<String,Object> values;

     public HeterogeneousContainer( Map<String, Class<?>> namesAndTypes )
     {
         this.namesAndTypes = new HashMap<String,Class<?>>( namesAndTypes );
         values = new HashMap<String,Object>( namesAndTypes.size() );
     }

     public <T> T get( String name, Class<T> type ) {
         if( type == namesAndTypes.get( name ) ) {
             return (T) values.get( name );
         }
         else {
             throw new IllegalArgumentException( "Pair (" + name + ", "+
                     type+") do not exist." );
         }
     }

     public <T> T put( String name, Class<T> type, T value ) {
         if( type == namesAndTypes.get( name ) ) {
             return (T) values.put( name, value );
         }
         else {
             throw new IllegalArgumentException( "Pair (" + name + ", "+
                     type+") do not exist." );
         }
     }

     public static void main( String[] args )
     {
         HashMap<String,Class<?>> namesAndTypes = new
HashMap<String,Class<?>>();
         namesAndTypes.put( "first", String.class );
         namesAndTypes.put( "second", Integer.class );
         HeterogeneousContainer test = new HeterogeneousContainer(
namesAndTypes );
         test.put( "first", String.class, "A String");
         test.put( "second", Integer.class, 4 );
         String s = test.get( "first", String.class );
         Integer i = test.get( "second", Integer.class );
         System.out.println( "Values: " + s + i );
     }

}

Hi Mark,

I pasted your code into Eclipse to look at it,
and I *do* get a warning on both return-statements:

Type safety: Unchecked cast from Object to T
 

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

Similar Threads


Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,134
Latest member
Lou6777736
Top