A question about generics

L

Lemon Tree

Hello,

I am wondering what is the most elegant (and correct) way to organize
the following type hierarchy.

Let's suppose to have the following parametric class:

class Foo<T extends InfoType> {
private T info;
...
public T getInfo() {
...
}
}

Let's now suppose that we want to create a Container for Foo instances,
and that we want to be able to search that container by using the info
contained in every Foo instance.

I might do the following:

class FooCollection<T extends Foo> extends HashSet<T> {
...
public T findByInfo(InfoType info) {
for(T t : this) {
if(t.getInfo().compareTo(info) == 0) {
return t;
}
}
return null;
}

Obviously the InfoType class contains an int compareTo(Bar info) method
for comparing InfoType (and their subclasses)

The previous code is correct but generates some warnings with respect
to the fact that the type parameter T is of type Foo and Foo is a
parametric type which is not instantiated with respect to its type
parameter.

In order to avoid the warnings I might do the following:

class FooCollection<T extends InfoType> extends HashSet<Foo<T>> {
...
public Foo<T> findByInfo(T info) {
...
}
}

This solution eliminates the warnings but I do not like it because when
I declare a FooCollection<InfoType>, by reading the declaration, it is
not clear that I am actually instantiating a collection of
Foo<InfoType> objects but it gives the impression that I am dealing
with a InfoType collection.

The third solution is to make explicit both the InfoType and the Foo
instances contained in the collection:

class FooCollection<T extends InfoType, S extends Foo<T>> extends
HashSet<S> {
...
public S findByInfo(T info) {
...
}
}

This also works, but when I have to declare a FooCollection I need to
do:
FooCollection<MyInfoType, Foo<MyInfoType>> which is a bit redundant and
unclear.

I do not see any other solution to how to structure the hierarchy.

In my opinion the most elegant and simple solution is the first one.
But I would like to get rid of the warnings. Do you know how to do
this? Can you suggest another more elegant solution (if it exists?)

Thank you
 
Z

zero

Hello,

I am wondering what is the most elegant (and correct) way to organize
the following type hierarchy.

Let's suppose to have the following parametric class:

class Foo<T extends InfoType> {
private T info;
...
public T getInfo() {
...
}
}

Let's now suppose that we want to create a Container for Foo
instances, and that we want to be able to search that container by
using the info contained in every Foo instance.

I might do the following:

class FooCollection<T extends Foo> extends HashSet<T> {
...
public T findByInfo(InfoType info) {
for(T t : this) {
if(t.getInfo().compareTo(info) == 0) {
return t;
}
}
return null;
}

Obviously the InfoType class contains an int compareTo(Bar info)
method for comparing InfoType (and their subclasses)

The previous code is correct but generates some warnings with respect
to the fact that the type parameter T is of type Foo and Foo is a
parametric type which is not instantiated with respect to its type
parameter.

<snipped>

I don't see the problem with your first version. If you instantiate a
FooCollection with FooCollection<Foo<InfoType>> col = new
FooCollection<Foo<InfoType>>();
you should not get any warnings. And it
is very clear that you are dealing with a collection of Foo objects -
and more specifically Foo<InfoType> objects.
 
L

Lemon Tree

I don't see the problem with your first version. If you instantiate a
FooCollection with FooCollection<Foo<InfoType>> col = new
FooCollection<Foo<InfoType>>();
you should not get any warnings. And it
is very clear that you are dealing with a collection of Foo objects -
and more specifically Foo<InfoType> objects.
It gives me a warning in the definition of the findByInfo method:

Type safety: The method getInfo() belongs to the raw type Foo.
References
to generic type Foo<T> should be parameterized

That's what I would like to remove.
But I am starting to think that it is not possible.
 
I

Ingo R. Homann

Hi,

Lemon said:
Hello,

class Foo<T extends InfoType> {
private T info;
...
public T getInfo() {
...
}
}

I think, this is the (only) "correct" solution:
class FooCollection<T extends InfoType> extends HashSet<Foo<T>> {
...
public Foo<T> findByInfo(T info) {
...
}
}

This solution eliminates the warnings but I do not like it because when
I declare a FooCollection<InfoType>, by reading the declaration, it is
not clear that I am actually instantiating a collection of
Foo<InfoType> objects but it gives the impression that I am dealing
with a InfoType collection.

Perhaps you can rename the classes, so that it becomes more obvious?
(Perhaps simply "CollectionFoo<InfoType>" or (IMHO not so good)
"CollectionOfFooOf<InfoType>")

Ciao,
Ingo
 
Z

zero

It gives me a warning in the definition of the findByInfo method:

Type safety: The method getInfo() belongs to the raw type Foo.
References
to generic type Foo<T> should be parameterized

That's what I would like to remove.
But I am starting to think that it is not possible.

The following quick test compiled without warnings for me.

Alternatively, have you tried

class FooCollection<T extends Foo<?>> extends HashSet<T>

This will tell the compiler you want a FooCollection of any type of Foo,
and you don't care which type - but this is still type-checked, unlike
the raw Foo in <T extends Foo>.


-- test code --

import java.util.HashSet;

public class GenericsTest
{
public static void main(String args[])
{
new GenericsTest();
}

public GenericsTest()
{
FooCollection<Foo<InfoType>> col = new FooCollection<Foo<InfoType>>();
}

private class InfoType implements Comparable<InfoType>
{
public int compareTo(InfoType i)
{
return 0;
}
}

private class Foo<T extends InfoType>
{
private T info;
public T getInfo()
{
return info;
}
}

private class FooCollection<T extends Foo> extends HashSet<T>
{
public T findByInfo(InfoType info)
{
for(T t : this)
{
if(t.getInfo().compareTo(info) == 0)
{
return t;
}
}
return null;
}
}
}
 
L

Lemon Tree

zero ha scritto:
The following quick test compiled without warnings for me.
Your code works without any warning.
I was suprised because your code is basically identical to mine (the
one which generated the warnings). But when I tried to split your code
in several files (a class per file) the warning appeared again!

I don't know why. It would be interesting to know.
Alternatively, have you tried
class FooCollection<T extends Foo<?>> extends HashSet<T>
Bingo!
That works even in the "splitted" layout.

Thank you for your help.
This will tell the compiler you want a FooCollection of any type of Foo,
and you don't care which type - but this is still type-checked, unlike
the raw Foo in <T extends Foo>.
Yes. That's what I missed before :)

Thank you again
 
Z

zero

zero ha scritto:

Your code works without any warning.
I was suprised because your code is basically identical to mine (the
one which generated the warnings). But when I tried to split your code
in several files (a class per file) the warning appeared again!

I don't know why. It would be interesting to know.

That is indeed surprising. I can't think of a reason that may be. Maybe
someone else here has an idea?
Bingo!
That works even in the "splitted" layout.

Thank you for your help.

Yes. That's what I missed before :)

Thank you again

My pleasure
 

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

No members online now.

Forum statistics

Threads
474,430
Messages
2,571,676
Members
48,796
Latest member
Greg L.

Latest Threads

Top