Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / December 2007

Tip: Looking for answers? Try searching our database.

Multiple type bounds

Thread view: 
kelvSYC - 06 Dec 2007 02:43 GMT
One thing that I've never been able to get in Java (or most
programming languages for that matter) is stuff like this:

How do you declare a parameter/variable/etc where the variable can be
any object that implements two different interfaces (or extends a
class and implements an interface)?  For example, suppose Foo is a
class and Bar and Baz are interfaces.  How do I create a function that
takes in an object that implements both Bar and Baz, or extends Foo
and implements Bar?  To me, this is entirely reasonable OO
programming.  And in Java, I've always resorted to declaring the
parameter as one thing and using reflection to see if it conforms to
the rest (and throwing an IllegalArgumentException if it does not) -
something like

void f(Foo foo) {
   Bar bar;
   try {
       bar = Bar.class.cast(foo);
   } catch (ClassCastException e) {
       throw new IllegalArgumentException();
   }
   // ... (since foo and bar now refer to the same thing, I use
whichever is appropriate)
}

I'd thought that when it comes to generics, I can't see that a similar
problem would appear, given that you can use multiple type bounds.
However, why is it that something like

List<? extends Foo & Bar> list = new ArrayList<? extends Foo &
Bar>();  // here, Bar is an interface, Foo can be either class or
interface

or

<T extends Foo & Bar> List<T> list = new ArrayList<T>();

Is it because of weird erasure behaviour?  Or is it because there is
still no way to do the first thing (the function with parameter as
described above), thus the second thing is illegal?  How do I work
around it (short of code duplication)?

Also, some of you may note that I could simply subinterface/subclass
to avoid the issue, and that is actually acceptable in some
scenarios.  However, suppose you have
class A extends Foo;
class B extends Foo implements Bar;
class C extends Foo implements Bar, Baz;
class D extends Foo implements Baz

Then List<? extends Foo & Bar> would mean, to me at least, a
homogeneous container (containing Bs and Cs, but not As).  Still, it
would avoid a lot of code duplication (for example, f() would have to
be rewritten to take a B and a C, and possibly anything you make later
matching the conditions)...
Patricia Shanahan - 06 Dec 2007 02:57 GMT
> One thing that I've never been able to get in Java (or most
> programming languages for that matter) is stuff like this:
[quoted text clipped - 14 lines]
>     try {
>         bar = Bar.class.cast(foo);

Why not "bar = (Bar)foo;" or an instanceof test?

Patricia
kelvSYC - 06 Dec 2007 04:40 GMT
> > One thing that I've never been able to get in Java (or most
> > programming languages for that matter) is stuff like this:
[quoted text clipped - 18 lines]
>
> Patricia

I've been largely taught to avoid explicit casting or instanceof
because they're evil.  But those are equally valid in the above, I
guess.
Andreas Leitgeb - 06 Dec 2007 11:29 GMT
>> >         bar = Bar.class.cast(foo);
>> Why not "bar = (Bar)foo;" or an instanceof test?
> I've been largely taught to avoid explicit casting or instanceof
> because they're evil.

While I don't even see, how "instanceof" could be considered
generally evil,  I see even less so, how .class.cast(...)
could be even a tiny bit less evil.

It's like: they told me not to rob people, so I kill them
first, because they didn't tell me not to rob corpses.
- except that I don't find instanceof to be any evil
in contrast to robbing :-)
Stefan Ram - 06 Dec 2007 03:15 GMT
>How do you declare a parameter/variable/etc where the variable can be
>any object that implements two different interfaces

 For example:

<T extends List<String> & RandomAccess> void foo(T list) { ... }
kelvSYC - 06 Dec 2007 04:54 GMT
> >How do you declare a parameter/variable/etc where the variable can be
> >any object that implements two different interfaces
>
>   For example:
>
> <T extends List<String> & RandomAccess> void foo(T list) { ... }

Well, that shows a function parameter (and I like the solution because
it fits in with what I believe is OO), but how about fields or local
variables?  If I use something like

private <T extends List<String> & RandomAccess> T
randomAccessStringList;

I get a syntax error (ReferenceType expected instead), even though
this seems to make sense.  Why is that?  Is there a way around this?
Stefan Ram - 06 Dec 2007 09:05 GMT
>private <T extends List<String> & RandomAccess> T
>randomAccessStringList;

class Example
< T extends java.util.List< java.lang.String >& java.util.RandomAccess >
{ private T randomAccessStringList; }
kelvSYC - 06 Dec 2007 17:25 GMT
> >private <T extends List<String> & RandomAccess> T
> >randomAccessStringList;
>
> class Example
> < T extends java.util.List< java.lang.String >& java.util.RandomAccess >
> { private T randomAccessStringList; }

Wouldn't that be genericizing the type?

Suppose you add a method

public setRandomAccessStringList(T list) { randomAccessStringList =
list; }

Then we have it that Example<ArrayList<String>> would accept setting
ArrayList<String> but not Vector<String>, while
Example<Vector<String>> would accept setting Vector<String> but not
ArrayList<String> - yet the original intention was for something that
could take both (and anything else that is both RandomAccess and
List<String>).  It seems that there is still no way (short of raw
types) to have a T so that Example<T> takes ArrayList<String>,
Vector<String>, or MyCustomRandomAccessStringList as arguments.

So now working backwards: suppose we have

public <T extends List<String> & RandomAccess>
setRandomAccessSringList(T list) { randomAccessStringList = list; }

as a method in Example.  How would you declare randomAccessStringList?
Lew - 07 Dec 2007 03:10 GMT
>>> private <T extends List<String> & RandomAccess> T
>>> randomAccessStringList;
[quoted text clipped - 24 lines]
>
> as a method in Example.  How would you declare randomAccessStringList?

T randomAccessStringList;

Signature

Lew

kelvSYC - 07 Dec 2007 04:33 GMT
> >>> private <T extends List<String> & RandomAccess> T
> >>> randomAccessStringList;
[quoted text clipped - 29 lines]
> --
> Lew

What I meant was that suppose Example was not generic - like so:

public class Example {
   public <T extends List<String> & RandomAccess>
setRandomAccessStringList(T list) { randomAccessStringList = list; }

   private ??? randomAccessStringList;
}

What would go in ???.
Piotr Kobzda - 11 Dec 2007 21:01 GMT
> What I meant was that suppose Example was not generic - like so:
>
[quoted text clipped - 6 lines]
>
> What would go in ???.

Try the following:

public class Example {
    public <T extends List<String> & RandomAccess>
            void setRandomAccessStringList(T list) {
        randomAccessStringListRef = new ListRef<T>(list);
    }

    private class ListRef<T extends List<String> & RandomAccess> {
        final T value;

        ListRef(T value) {
            this.value = value;
        }
    }
    private ListRef<? extends List<String>> randomAccessStringListRef;

    // randomAccessStringListRef.value is both List<String> and
RandomAccess, without any explicit cast needed
}

piotr
Piotr Kobzda - 12 Dec 2007 09:08 GMT
... and a few improvements:

>     private class ListRef<T extends List<String> & RandomAccess> {

Inner class is not needed here, static is enough.

>         final T value;
>
[quoted text clipped - 3 lines]
>     }
>     private ListRef<? extends List<String>> randomAccessStringListRef;

The list reference holder field may be declared also with unbound
wildcard, i.e.:

    private ListRef<?> randomAccessStringListRef;

Every bound of ListRef's type variable (an intersection type) is known
by the compiler, so effectively we have equivalent of the following (not
allowed by the language) declaration:

    private ListRef<? extends List<String> & RandomAccess>
randomAccessStringListRef;

piotr
kelvSYC - 13 Dec 2007 17:32 GMT
The wrapper idea is a good one, but how does it do in other
situations?  For example, you wanted something like

private <T extends List<String> & RandomAccess> Map<Class<? extends
T>, T> randomAccessStringListClassesAndInstances; // some kind of
prototype-flyweight-manager-thing

So you'd make a wrapper for the map (call its instance
randomAccessStringListClassesAndInstancesWrapper), but how would you
go about instantiating the wrapper (in particular, what type bounds
should I put down), and say do something like

randomAccessStringListClassesAndInstancesWrapper.value.put(ArrayList.class,
new ArrayList<String>()); // I realize that the ArrayList part is an
issue unto itself, but let's ignore it here
randomAccessStringListClassesAndInstancesWrapper.value.put(Vector.class,
new Vector<String>());
Roedy Green - 06 Dec 2007 09:20 GMT
>How do I create a function that
>takes in an object that implements both Bar and Baz,

1. You create a new class, possibly abstract, that implements both Bar
and Baz.

2. You use generics where you can apply multiple restrictions.

3. You declare one class for automatic checking then use instanceof to
check if the other were indeed supplied.
Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Daniel Pitts - 06 Dec 2007 20:07 GMT
> One thing that I've never been able to get in Java (or most
> programming languages for that matter) is stuff like this:
[quoted text clipped - 51 lines]
> be rewritten to take a B and a C, and possibly anything you make later
> matching the conditions)...

I wrote a blog post about this a short while ago
<http://virtualinfinity.net/wordpress/java/esoteric-java-features/2007/11/23/type
-intersection/
>

Basically, I feel that its a feature that Sun should have added when
they added it for Generics, but it got left out for some reason.

Signature

Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Daniele Futtorovic - 07 Dec 2007 04:50 GMT
> One thing that I've never been able to get in Java (or most
> programming languages for that matter) is stuff like this:
[quoted text clipped - 5 lines]
> takes in an object that implements both Bar and Baz, or extends Foo
> and implements Bar?  

Use two parameters.

What's the point in forcing the data/functionality you need to perform
your method to be contained within one object? On the contrary, allowing
distinct objects provides more flexible access and allows for later
restructuration of your calling architecture.

DF.


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.