Reputation: 311
Given the following C# code, how can I translate this to Java?
public class Stop : IComparable<Stop>
{
public int CompareTo(Stop other) { ... }
}
public class Sequence<T> : IEnumerable<T>
where T : IComparable<T>
{
public IEnumerator<T> GetEnumerator() { ... }
IEnumerator IEnumerable.GetEnumerator() { ... }
}
public class Line<T> : Sequence<T>, IComparable<Line<T>>
where T : Stop
{
public int CompareTo(Line<T> other) { ... }
}
I have difficulties translating the definition of class Line to Java. My first attempt would be the following:
public class Line<T extends Stop> extends Sequence<T> implements Comparable<Line<T>> { ... }
However, the compiler reports the following error for extends Sequence<T>
:
Error: type argument T is not within bounds of type-variable T
Changing the definition to
public class Line<T extends Comparable<T>> extends Sequence<T> implements Comparable<Line<T>> { ... }
fixes the error, but does not accurately reflect the intent: I want to enforce that all type arguments used with Line must be a sub-type of Stop. Using T extends Comparable<T>
would allow arbitrary types that implement the interface.
I do not understand the reason for the error. Is there some way to express this relationship without changing the structure of the types or is this a limitation of Java's generics?
Edit: Visit https://www.onlinegdb.com/S1u9wclnH to see a stripped down version of my attempt.
Upvotes: 1
Views: 99
Reputation: 16464
The problem is your definition of class Sequence
.
public class Sequence<T> : IEnumerable<T>
where T : IComparable<T> { ... }
This C# class makes use of the fact that IComparable
is contra-variant, so the C# class doesn't require exactly T: IComparable<T>
, but is also happy if T
is comparable with one of its base classes. Thus the code works even if T
is instantiated with a class derived from Stop
.
Java does not have declaration-site variance, but use-site variance (wildcards). Your Java Sequence
class cannot be instantiated for classes derived from Stop
, but your Line
class might be. Thus the compiler error.
To fix this, you need to translate C#'s declaration-site variance to Java's wildcards whenever you use Comparable
in bounds:
class Sequence<T extends Comparable<? super T>> implements Iterable<T> { ... }
Upvotes: 1