Skip to main content

Again .... generic woes ...

7 replies [Last post]
Anonymous

Again, totally confused .. here's the setup:

assume we have both an interface and a class with the same method (guess
what I'm playing with )

<br />
public class SomeClass {<br />
    public void setSortKeys(List<? extends SortKey> keys) {<br />
        // do nothing<br />
    }<br />
}</p>
<p>public interface SomeInterface {<br />
    public void setSortKeys(List<? extends SortKey> keys);<br />
}<br />

Now extend SomeClass and make it implement the interface, like

<br />
public class SomeMix extends SomeClass implements SomeInterface {</p>
<p>    @Override<br />
    public void setSortKeys(List<? extends SortKey> keys) {<br />
        // do ... whatever<br />
    }</p>
<p>}<br />

Now in SomeMix, replace "extends SomeClass" with "extends
DefaultRowSorter" (or TableRowSorter) - and it doesn't compile, the errors:

Name clash: The method setSortKeys(List<? extends RowSorter.SortKey>) of
type SomeMix has the same erasure as setSortKeys(List) of type
DefaultRowSorter but does not override it

What's going wrong, and why does the replacement make a difference?

Thanks
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
kschaefe
Offline
Joined: 2006-06-08

Here's the deal:
[code]public interface A {
void set(T object);
}

abstract class B {
abstract void set(T object);
}

class C extends B implements A {
public void set(X object); //error
}[/code]
The compiler is still expecting a method for A (bound to raw): set(Object object). The problem is that when the generic type information is erased B.set and A.set have the same signature, but may not refer to the same method (in this case B.set(X) and A.set(Object)).

Anyway, you will need to type the interface the same as the extended class or similarly named methods will clash.

Karl

Kleopatra

Kleopatra schrieb:
>
> [code]
> public class SomeMix extends SomeClass implements SomeInterface {
>
> @Override
> public void setSortKeys(List keys) {
> // do ... whatever
> }
> }
> [/code]
>
> Now in SomeMix, replace "extends SomeClass" with "extends
> DefaultRowSorter" (or TableRowSorter) - and it doesn't compile, the
> errors:
first, better replace with "extends TableRowSorter" which doesn't
compile. But "extends TableRowSorter" is okay.

Hmm ... still puzzled. Is the parameter needed? If so, might it be
Eclipse not coming up with the correct error message?

Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

osbald
Offline
Joined: 2003-06-13

I'm not sure what SortKey is here, but you're specifying it a a low bound on those lists. Those lists would have to contain SortKey(s) or any of SortKeys supertypes. Which is what.. ? Object?

david_hall
Offline
Joined: 2003-06-12

>> Those lists would have to contain SortKey(s) or any of SortKeys supertypes

Subtypes, not supertypes, and even that is slightly inaccurate. It's not so much a list of objects derived from SortKey -- it's better to read it as a List of objects of some arbitrary class that derives from SortKey.

Jeanette:

Essentially, the problem is type erasure. You're not overriding the base class method, your overloading its name. In your base class and in your interface, you declare that you can use a list containing any subclass of SortKey. In your implementation, you overload that method with a specialization for handling one specific subclass of SortKey. The basic problem is that both the base class method and your derived class method take a list, and once the generic types are erased, the two methods have the same signature, so the compiler can't tell the difference.

I suspect you don't have the flexibility to change the interface: what I'd typically do if I was starting from a blank slate would be to make SortKey a generic parm:

[code]
public class SomeClass {
public void setSortKeys(List keys) {
// do nothing
}
}

public interface SomeInterface {
public void setSortKeys(List keys);
}

public class SomeMix extends SomeClass implements SomeInterface {

@Override
public void setSortKeys(List keys) {
// do ... whatever
}
}

[/code]

Kleopatra

Dave,

thanks for your explanation - your solution looks fine. Only I'm can't
make it fit to my context: the parameterization of the method is
unrelated to the parameterization of the class (at least I think so :)

maybe a bit more context to try and clarify. It's all about JXTable and
Mustang sorting:

- Mustang RowSorter is the equivalent of SomeClass
- RowSorter is parameterized on the type of model and Identifier
- to characterize sort state, it manages a list of (Mustang) SortKeys in
a list of objects which are SortKeys or subclasses
- to ease the transition, SwingX had defined a SortController interface
which is a subset of the RowSorter methods (the part that's used by the
views to change/toggle sorts). That's the equivalent of SomeInterface
- the SortController itself is not parameterized (should be usable for
all sortable components, doesn't care about the typing)
- SortController manages the list of objects which are (Mustang)
SortKeys or subs same as RowSorter does
- a Mustang JXTable will use a default XRowSorter which extends
RowSorter and implements SortController to keep the best of both worlds
(at least that's the plan ;-) This XRowSorter is the SomeMix ...

with the real-world names:

[code]

// parameterized on the model type
class TableRowSorter extends .... {
// accessing the list containing SortKey or subclasses
public void setSortKeys(List keys);
}

// not interested in any particular model, so unparameterized
interface SortController {
// subset of methods, same type restriction as in the RowSorter
public void setSortKeys(List keys);
}

class XTableRowSorter
// with this it doesn't compile
//extends TableRowSorter
// with this it compiles (and works)
extends TableRowSorter
implements SortController {
// might be overridden to do some additional work
public void setSortKeys(List keys) {
}
}
[/code]

Hmm ... ahhhh ... think I got it (partly): not the implements is the
trouble, but not parameterizing the subclass of TableRowSorter?

Dooh ... generics are just too much for me. But thinking publicly helps
Thanks everybody for listening!

Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

david_hall
Offline
Joined: 2003-06-12

I'm guessing that the way that you're going to use it is to pass a different List of SortKeys for each column in the table? If that's the case, then why don't you try to remove the wildcards entirely?

[code]
class TableRowSorter extends .... {
// accessing the list containing SortKey or subclasses
public void setSortKeys(List keys);
}

// not interested in any particular model, so unparameterized
interface SortController {
// subset of methods, same type restriction as in the RowSorter
public void setSortKeys(List keys);
}
[/code]

Where will the lists be coming from? If the source of the list is (or can be) declared as List, then you should be fine omitting the wildcard. Where you'll bump into limits is if the user has a reference to a List, he won't be able to use it with methods that require a List.

dave

Kleopatra

jdnc-interest@javadesktop.org schrieb:
> I'm guessing that the way that you're going to use it is to pass a different List of SortKeys for each column in the table? If that's the case, then why don't you try to remove the wildcards entirely?
>
>
they may or may not be of a derived type, so I think the wildcard is
needed. Just to clarify: the base error (mine) was the extend of the
TableRowSorter (independent on whether the sortController was implemented)

[code]
// the core class
class TableRowSorter ... {
// somemethod
}
// The wrong extend I did:
class MyTableRowSorter extends TableRowSorter {
@override
// somemethod
}

// the compiling version
class MyTableRowSorter extends TableRowSorter {
@override
// somemethod
}

[/code]

Thanks for all your help!
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net