Can a non-generic class implement a generic interface? - java

I've been reading "Java. A Beginner's Guide" by Herbert Schildt. In the section on generic interfaces on one page the author writes (emphasis mine):
Any class that implements a generic interface must itself be generic.
And on the next page (emphasis mine):
In general, if a class implements a generic interface, then that class must also be generic, at least to the extent that it takes a type parameter that is passed to the interface.
So are there any specific situations where a non-generic class can implement a generic interface in Java? Or all such classes are generic in that they 'inherit' that generality from the generic interface?
UPD: I should have read the section further. The author goes on to state:
Of course, if a class implements a specific type of generic interface, such as shown here:
class MyClass implements Containment<Double> {
then the implementing class does not need to be generic.
This is, I believe, the gist of all the answers to my post.

It is possible to create a non-generic class that implements a generic interface, provided that the type parameters are provided.
A relatively simplistic example:
public class LocalDateParser implements Function<String, LocalDate> {
public LocalDate apply (String s) {
return LocalDate.parse(s);
}
}
Of course, you can only assign an instance of this class to Function<String, LocalDate>, and not to any other Function<T, R>.

I think the author is plain wrong in both statements. A generic class is a class that accepts a generic type parameter. And you can create a class that doesn't accept any generic type parameter that implements a generic interface:
public class CaseInsensitiveComparator implements Comparator<String> {
#Override
public int compare(String s1, String s2) {
return s1.compareToIgnoreCase(s2);
}
}
In fact, this class already exists in the JDK, though it's implemented differently. Please see String.CASE_INSENSITIVE_ORDER for further details.

The guide you're reading is wrong.
There are many examples of non-generic classes implementing generic interfaces.
The most common one is Comparable<T>. The Java 8 javadoc lists 152 implementing classes, few of which pass on a generic type argument to the interface, since they are all supposed to specify themselves as the argument to Comparable, e.g.
public final class String implements Serializable, Comparable<String>, CharSequence
public final class Integer extends Number implements Comparable<Integer>
public final class Instant implements Temporal, TemporalAdjuster, Comparable<Instant>, Serializable

Related

Reference implementing class from interface definition

Given an interface I:
interface I<T> {
public abstract T doSomthing(T other);
}
where any class C which implements the interface I will always use itself (C) as the type parameter:
class MyClass implements I<MyClass> {
#Override
public MyClass doSomthing(MyClass other) {
return null;
}
}
Is there a way to accomplish this without explicitly passing the class C as the parameter every time a new class implements the interface?
In other words is it possible, in an interface, to reference the class which implements that interface?
tl;dr
You asked:
Is there a way to accomplish this without explicitly passing the class C
No, not in Java.
Example
You seem to be describing exactly the scenario of the Comparable<T> interface bundled with Java. That interface has a single generic argument, for the type of the two objects to be compared. That interface requires a single method compareTo​(T o) taking a single parameter of that same generic type.
Let’s look at an example usage in the OpenJDK source code, the source code for class Year.
The class declares itself explicitly as the type of comparison on the Comparable interface being implemented.
public final class Year
implements Temporal, TemporalAdjuster, Comparable<Year>, Serializable {
The compareTo method explicitly cites its own class as the type being compared.
#Override
public int compareTo(Year other) {
return year - other.year;
}
You asked:
Is there a way to accomplish this without explicitly passing the class C as the parameter every time a new class implements the interface?
It seems the answer is No. The implementing class must cite itself explicitly as the fulfillment of the generic type of the interface being implemented.
Caveat: (a) I am not an expert on such language matters. (b) I may have misunderstood your question.
To add to the other answer: what you're describing is a self type.
Some other languages have it (such as Scala).
But I'm afraid Kotlin doesn't.  (Java doesn't, either.)
There has been long discussion about the possibility of adding it to a future version of Kotlin; it seems the potential uses may not be wide enough for it to be worthwhile, though there doesn't seem to be a final consensus.
The usual workaround is using a type parameter — similar to what C++ calls the curiously-recurring template pattern.  It's not quite as typesafe in Java or Kotlin, as this question illustrates, but covers most of the same ground.
That's called self-bounded generics. It could be declared in Java as well as in Kotlin.
Java:
interface I<T extends I<T>> {
public abstract T doSomething(T other);
}
Kotlin:
interface I<T : I<T>> {
fun doSomething(other: T): T
}
But it doesn't mean, that generic parameter could be omitted then you declare classes, implementing this interface. It just imposes additional restrictions on type, you're passing as a generic parameter (narrowing it down to only one type). Type inference is not supported for class declaration neither in Kotlin, nor in Java.
Also see: Can I resolve a generic type from another generic declaration in an interface?

How to create a generic type that only allow a specific class to extends/implements it

For example, I want to create a generic interface IEnum and make sure that every IEnum instance is also an enum constant, in other words, only enum type can implement IEnum. Does java support such feature or can it be achieved by any workaround? Can it be achieved by recursive Bounded Type Parameters?
You can use a recursive bounded and a union type parameter, to enforce that the the passed generic class is an Enum and implements IEnum:
public interface IEnum<E extends Enum<E> & IEnum<E>> {}
Note: the order matters, so the first type can either be a class or interface, but everything that follows it must be an interface.
You can then use it like this:
public enum Foo implements IEnum<Foo> {}
Sadly, you can't force the implementing class to pass itself as a type parameter, e.g. this would work:
public class Bar implements IEnum<Foo> {}
Also you can't constrain the implementation to not use raw types, e.g. this would also work:
public class Baz implements IEnum {}

Recursive interface type parameter in Java

I am trying to understand this recursive interface definition in apache thrift source code
public interface TBase<T extends TBase<?, ?>, F extends TFieldIdEnum> extends Comparable<T>, Serializable {
From my understanding TBase is a interface containing type parameter T and F.
T has the constraint that it also have to be extending TBase that has type parameter containing any type.
What I am confused about is what is the terminating TBase
Say I have
public class TBaseImpl<A, B> implements TBase<A, B>
A has to be a TBase
so there must be another class implement A
public class TBaseImplA<C, D> implements TBase<C, D>
but C have to be a TBase
so there must be another class implement C
This goes on forever.
So my question is
What is terminating condition for TBase
What is the benefit of this recursive definition?
Can someone point me a direction?
Thanks
so there must be another class implement A
That is not necessarily true. With this type of recursive bounds, there are 2 possible ways to satisfy the constraint when creating a subtype.
Declare your own type parameter with the same or more restrictive bounds. This places the burden of choosing the type parameter on the user of this class.
public class TBaseImpl<A extends TBase<A, B>, B extends TFieldIdEnum> implements TBase<A, B>
or more likely
public class TBaseImpl<A extends TBaseImpl<A, B>, B extends TFieldIdEnum> implements TBase<A, B>
Pass the same class as what you're defining to satisfy the original bound.
public class TBaseImpl<B extends TFieldIdEnum> implements TBase<TBaseImpl, B>
A benefit of this pattern is being able to restrict the parameter of a method that is meant to take in another instance of the same class, e.g.:
public void example(T other)
This is (in Java) the Curiously Repeating Template Pattern.
Normally an implementing/overriding method must match the parameter types and order of parameters exactly. But this pattern allows you to narrow the type by narrowing the type parameter. E.g. such a method in TBaseImpl in this case would only take a TBaseImpl and not the broader T or TBase. In such a class there is a relationship between the class and itself.
Another benefit is method chaining, in which a method returns this to allow
obj.method1().method2().method3()
In this way, chaining methods can be declared to return T, so that e.g. a TBase<TBaseImpl> variable can call these methods, each returning a TBaseImpl on which another method can be called.
T method1(); // in TBase
#Override
TBaseImpl method1(); // in TBaseImpl
Incidentally, if you're trying to declare a type variable that is a subtype of an enum, that's not necessary because an enum is final and cannot be extended. It would be simpler to remove F in the interface and have implementing classes use the enum directly.

Java - generic class parameter with a generic parameter

how do I correctly write following class declaration in Java?
public class BinarySearchTree<T extends BinarySearchNode<E implements Comparable<E>>> implements Iterable<E>
Basically, I am trying to create a BinarySearchTree of any class T that inherits BinarySearchNode of a Comparable datatype E (And my BinarySearchTree should also be Iterable).
How can I properly declare that class in Java?
Thanks!
public class BinarySearchTree<T extends BinarySearchNode<E>, E extends Comparable<E>> implements Iterable<E>
The type parameter E needs to be defined separately from the node type, even if it ends up looking redundant: BinarySearchTree<BinarySearchNode<String>, String>. Java won't let you directly access a generic parameter of a generic type.
Also, note that generic parameters always use "extends" even with interfaces.
With Generics in Java, you will only use extends. So, essentially your method decoration would become:
public class BinarySearchTree<T extends BinarySearchNode<E extends Comparable<E>>> extends Iterable<T>
Even for those classes that implement an interface, generics will use extends. The only other syntax for generics is super if you are looking at the inheritance from the opposite direction

Generic extends and implements

I don't understand why Company compiled. I thought it checked for extends but not for implements?
public interface Employee
public class HourlyEmployee implements Employee
public class Company<T extends Employee>
Company<HourlyEmployee> company = new Company<>();
The extends keyword in Generics has a slightly different semantics than the general extends keyword.
When using extends in the context of Generics, for example T extends Something, this means that T should be a type that either implements the interface Something (in cases when Something is interface), or is a subclass of Something (in case Something is a class).
Probably the reason for this is that if the implements keyword was supported in Generics, this would have made type-parameter declaration too verbose.
For example, you'd have:
<T extends SomeClass implements Serializable & Observable>
Instead, the valid syntax for this would be:
<T extends SomeClass & Serializable & Observable>
And you don't need to have the implements keyword, actually. When defining the bounds of a type T, you just need to point out which types does your type T derive from, without caring if those are interfaces or classes.
The type definition is not a class definition. You can consider type definition as joining few data sets, where the resulting set is your type T.
The notation T extends Employee in the declaration of a type parameter refers to either extending a class or implementing an interface.
public class Company<T implements Employee> is not a valid syntax.
Therefore public class Company<T extends Employee> means that the generic type parameter T of your Company class must implement the Employee interface.

Categories

Resources