Please explain the custom 'T' in the java interface. It is using generics here and of type 'T' i suppose. Then where is the type 'T' defined?
public interface TemplateBuilder<T extends TemplateBuilder>
T is not an actual class. It is determined at compile time depending on the usage of your class TemplateBuilder. Just think of it as a place holder for various possible types, one of which is 'chosen' depending on your circumstances.
For a simpler example, look at the following (adapted from Java's tutorial):
Imagine you want to declare a class Box, which can take a specific type (of the object to hold inside the box), but you wish to reuse this in various circumstances to hold various different types.
So instead of fixing the actual type the Box can take, you declare it as follows:
public class Box<T> {
private T t; // T stands for "Type"
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
When you use it, you then do something like:
Box<Integer> integerBox = new Box<Integer>();
Whats the whole point you might ask? Why not make Box take an Object?
In fact before Java 1.5 this was not possible. This was introduced to have further type-safety in these situations, and was adopted in the Collections framework.
The whole point is that without this mechanism, if instead it used Object, you can't force a specific instance of your Box to hold only Integers. On the other hand, if you made it use specifically Integers, you can't reuse your Box for String, or other objects, and you would need to create another type of Box class.
Before Java 1.5, objects like ArrayList took plain Objects, however there were often cases of type safety broken at runtime, because the program is assuming a list of Integer objects and by mistake somewhere a String is inserted. Generics (through this magic T) force types without restricting what they might be.
In your case T extends TemplateBuilder is going one step further and stating that whatever T is, it must be a class that extends TemplateBuilder. If that wasn't there, it would be any class that extends Object (the universal base class of Java).
T is any Object that extends from TemplateBuilder
T means any Object. for example
List<T> list = new ArrayList<T>();
here T can be Integer, String ...
and <T extends A> means any Object T extends from A
This type is defined when implementing the interface, i.e.
class StringBuilder implements TemplateBuilder<StringBuilder> {}
BTW, see class Enum (the base class of all enums).
My Custom Generics Explanation
Backgorund:
Custom generics are used invariably with data structures e.g. when managing(storing/retrieving) lists of "things"
You do not need to do your own type checking in order for the code to compile as custom generics incorporates the principles of polymorphism.
However, in contrast to the "traditional" OO principles of polymorphism, a class can store a list of things without having any relationship with the "thing(s)" it is storing (The Fundamental Principle of OO where A is a super class of B class is not required)
You do not make separate subclasses for every possible kind of class of "things" you wish to store.
Example 1
As an example consider the following two classes below which are unrelated. This is a very primitive example but nonetheless gives an outline of the principles of custom generics:
/**
*
* Class A is a Custom Generic class that can be 'typed'
* to any kind of class using diamond 'T' syntax.
*
*/
class A<T>
{
// The instance variable of the object type 'T' known at run time
T theI;
// The constructor passing the object type 'T'
A(T anI)
{
this.theI = anI;
}
// Method to return the object 'T'
T getT()
{
return theI;
}
}
Below is the class B which is unrelated to class A i.e. B does not extend A:
/**
*
* Simple class which overrides the toString()
* method from Object's class toString() method
*
*/
class B
{
#Override
public String toString()
{
return "B Object";
}
public static void main(String[] args)
{
A<B> a = new A<>(new B());
System.out.println(a.getT());
}
}
In Main method of class B above:
a.getT() returns the object 'T' which in this example is of type 'B' (This is an example of polymorphism).
a.getT() returns the object 'T', object instance C's method toString() gets IMPLICITLY called, as it is overriding Object's toString() method and prints "B Object".
The interesting aspect to note about Custom Generics and polymorphism is that:
In the context of custom generics, there are no constraints for a relationship among classes in order to execute polymorphism
e.g. Class B is unrelated to A above i.e class B DOES not extend A.
In "traditional" object orientated polymorphism principles, there is invariably a requirement constraint for classes to be related in some way. However, this is not required in custom generics.
Example 2
public interface TemplateBuilder<T extends TemplateBuilder>
The above means that TemplateBuilder interface can be typed to any class that extends TemplateBuilder.
Let's assume SomeClass extends TemplateBuilder then the following is fine:
TemplateBuilder<SomeClass> tbRef = ...
/* Using an Anonymous Inner Class reference to interface TemplateBuilder<SomeClass> */
or
TemplateBuilder<SomeClass> tbRef = .... /* Referencing a concrete class
that implements TemplateBuilder */
Related
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?
I am having some (philosophical?) problems with java's generics...
Consider the following
public interface ClassA<I> {}
public class Obj implements ClassA<String> {}
public interface ClassB<I, T extends ClassA<I>> {
public I getSomething();
public T getAnotherThing();
}
This compiles and works ok, if an object of ClassB is instantiated as:
ClassB<String, Obj<String>> o = new ClassB<>();
o.getSomething(); // <-- Returns String
I was wondering if there is a way to avoid instantiating a ClassB object without having to specify the String generic as well, since it's already inside ClassA. More specifically, I'd like to use it as:
public interface ClassB<T extends ClassA<I>> { // <-- Won't compile
public I getSomething();
}
ClassB<Obj> o = new ClassB<>();
o.getSomething(); // <-- Returns String from Obj declaration, which uses ClassA<String>
I know the "problem" can be easily gotten over with the first example, but I wanted to know if there's a way of reference the actual type of the generic in the implementing ClassA object without having to pass it again in ClassB's declaration, and if not, why.
Hope I was clear enough with my dilemma.
Thanks
I think the answer is "No". :)
Java doesn't provide a way to extract a type argument from a type itself, only from an argument having that type.
Eg:
class ClassB<T extends ClassA<?>> {
<I> I getSomething(ClassA<I>) { ... }
}
... works fine and could be passed an instance of T in order to extract I. But to remove the parameter from the method (which is used only to determine the type for I) you'd need a way to determine I from T itself, and there is no such way.
In general, type inference in Java is limited to establishing a relationship between parameter types and/or between parameter and return types.
The other way, then, would be to declare I and T together as part of one generic parameter, as you tried:
public interface ClassB<T extends ClassA<I>>
But then, as you noted, this is not accepted either. Java's syntax would need to be expanded in order to allow this.
I was wondering, aside from syntactic difference, when would one use a generic interface over a method that accepts a generic parameter?
public interface Flight<T>{
void fly(T obj);
}
over
public interface Flight{
void <T> fly(T obj);
}
If you declare a generic method, you always let the caller decide, which type arguments to use for the type parameters. The implementation of the method must be able to deal with all possible types arguments (and it doesn’t even have a way to ask for the actual type arguments).
That said, a method like <T> void fly(T obj); states that the caller may use any type for T while the only thing the implementation can rely on is that the actual type for T will be assignable to Object (like if <T extends Object> had been declared).
So in this specific example, it’s not different to the declaration void fly(Object obj);, which also allows arbitrary objects.
In contrast, a type parameter on an interface is part of the contract and may be specified or restricted by an implementation of the interface:
public interface Flight<T>{
void fly(T obj);
}
allows implementations like
public class X implements Flight<String> {
public void fly(String obj) {
}
}
fixing the type of T on the implementation side. Or
public class NumberFlight<N extends Number> implements Flight<N> {
public void fly(N obj) {
}
}
being still generic but restricting the type.
The signature of an interface is also important when the interface itself is a part of another method signature, e.g.
public void foo(Flight<? super String> f) {
f.fly("some string value");
}
here, the Flight implementation, which you pass to foo, must be capable of consuming a String value, so Flight<String> or Flight<CharSequence> or Flight<Object> are sufficient, but not Flight<Integer>. Declaring such a contract requires type parameters on the interface, not at the interface’s methods.
You should use a generic type when you expect that most of the methods, in the implementations, will perform operations on the type supplied when instantiating the class.
For example, ArrayList<E> is a generic type since most of its operations (add, get, remove etc.) rely on the type specified upon creation of one.
A generic method should be used when only a few methods in the class rely upon the different types.
You can read more about generics in the Java Docs.
Take for example the class java.util.ArrayList<E>. When creating variables of that type, you have to specify a concrete type for T:
ArrayList<String> list = new ArrayList<>();
These concrete types are used, when calling methods from the List interface, that work with the type T. Calling the add method, you can only add String objects to the list. Retrieving elements from the list using get, you will get elements of the concrete type String.
For generic methods, the type T is specified only for this method. And it would make more sense if the methods returns a value of that generic type. You often find code like this:
MyObject obj = SomeClass.staticGenericMethod(MyObject.class)
or
MyObject obj = classInstance.genericMethod(MyObject.class);
And you should start your interface name with a capital letter: Flight<T>
Have a class Car with a public method
public Car myself() {
return this;
}
Have a subclass Ferrari, and a variable foo that contains a Ferrari object.
Finally,
Ferrari bar = foo.myself();
This will warn you, because the method myself() returns a Car object, rather than the expected Ferrari.
Note: I know that the example is stupid because you'd just do bar = foo. It's just an example.
Solutions:
Override the myself() method in Ferrari.
Cast the Car object to a Ferrari object when assigning bar.
Both solutions work and I am okay with that. However, the first one is undesirable when you have several subclasses of Car. I feel that overriding a method over and over defeats the point of inheriting it. Next, regarding the second solution, casting is not pretty. It feels silly - if my variable is of type Ferrari, shouldn't Java be able to implicitly cast it without warning me? After all, Java must know that the returned object can be casted to Ferrari, no?
Is there another workaround? Just out of curiosity - I can live with casting stuff, telling Java what things are supposed to be...
This solution uses generics in a way that is used more often in the Java libraries.
It works and you don't have to cast the result every time nor override the myself method in every subclass.
I believe that it is the only solution that doesn't require overriding or casting. It does require each subclass to use its own type as a type parameter to the superclass Car: class Ferrari extends Car<Ferrari>
class Car<X extends Car<X>> {
public X myself() {
return (X) this;
}
}
class Ferrari extends Car<Ferrari> {
}
And then use it as you intended:
Ferrari testarossa = new Ferrari().myself();
This concept is used in the Java standard libraries a few times as well in one way or another:
java.lang.Enum
public abstract class Enum<E extends Enum<E>>
java.util.Comparable
public interface Comparable<T>
(You're supposed to pass your own class type when you implement a comparable: class ShoeSize implements Comparable<ShoeSize>)
Method chaining
There's a good use for this too - there is a pattern, favored by some, that allows method chaining. This is what StringBuilder does: new StringBuilder().append("a").append("b").toString(). However a class that supports method chaining is often hard to subclass. Using the approach I outlined above makes it possible to subclass in this situation.
This also depends on how you know the foo variable.
If you know it by
Ferrari foo = new Ferrari();
then an overridden method like
class Ferrari extends Car {
#Override
public Ferrari myself() {
return this;
}
}
will allow you to exploit the covaraince, and you can do
Ferrari foo = new Ferrari();
Ferrari bar = foo.myself();
although there are probably not many application cases where this makes sense: When you already know that it is a Ferrari, you could just write
Ferrari bar = foo;
The situation is different when you only know it by
Car foo = new Ferrari();
Then you're out of luck: You don't know the runtime type any more, and you'll have to cast anyhow.
(Note: Such an overridden method returning this with a more specific type has a real application case when it comes to self-referential generic types. This is sometimes referred to as the getThis trick)
Concerning your statement
It feels silly - if my variable is of type Ferrari, shouldn't Java be able to implicitly cast it without warning me? After all, Java must know that the returned object can be casted to Ferrari, no?
This is not true. No one prevents you from overriding the method like
class Ferrari extends Car {
#Override
public Car myself() {
return new Volkswagen();
}
}
and then the cast would no longer be valid
A sub-class may override a base-classes method, and as part of that contract indicate that it will return the specific type. This provides clarity to the user of the class, whereas expecting the user to know the type being returned and cast it accordingly does not. Therefore, overriding is better.
I'm not sure if this is possible or not, but what I want to accomplish is this:
public static <A,B extends SomeClass & A> B makeB(A thing) {...}
Essentially, using a reflection/generation driven process, I want to provide a thing of type B, where B is of class SomeClass and implements interface A, and A is user-supplied through Generics.
I am not asking about the mechanics of generating B - I have that under control. What I'm looking for is a way to restrict generic type argument <A> to interfaces, not classes, so that I can use the syntax B extends SomeClass & A for clean type safety.
Is this possible? Is anyone aware of an alternative approach to this problem?
Edit: I guess I didn't express myself very clearly, as it seems to be causing confusion in the comments:
B is intended to be a placeholder for a wildcard, so that the client can get a single object that is both a SomeClass and an A without having to do casting based on trust. The client will not have access to the name of the actual class that implements SomeClass and A, because it's being generated at compile time, hence this issue regarding type safety.
It's impossible to impose such a compile-time restriction. Generic type parameters are stand-ins for reference types; they make no distinction between class types and interface types. The fact that additional bounds in a type parameter's declaration must be interface types is merely incidental - your strategy to leverage this as a means to impute a type as an interface was clever, but it's defeated by the limitation that type parameters can't be used in multiple bounds.
Your only options are to settle for a runtime check using Class.isInterface() like Louis Wasserman pointed out, or to leave it up to the caller to be responsible with what it passes in. Either way, make sure to clearly document the method's expectations and behavior.
B is intended to be a placeholder for a wildcard, so that the client can get a single object that is both a SomeClass and an A without having to do casting based on trust. The client will not have access to the name of the actual class that implements SomeClass and A
This seems like a contradiction to me. There's no point to declaring B if the caller can't possibly know what it evaluates to. Remember: the caller of a generic method provides its type arguments. So a caller deciding B without anything to base it on can only be guessing - and that can never be type-safe.
It seems like what you really want your method to return is some type that is both a SomeClass and an A, but this is tricky because they don't share a common supertype:
public static <A> SomeClass&A makeSomeClass(A thing) {...}
(this is nonsensical syntax for demonstration purposes only)
As a workaround, consider alternative ways to represent both a SomeClass and some interface type. For example the candidate interfaces could have a common method for returning a SomeClass:
public interface IsSomeClass {
SomeClass asSomeClass();
}
public interface Foo extends IsSomeClass { }
The implementation of asSomeClass would in fact just return this. Then you could do:
public static <A extends IsSomeClass> A makeSomeClass(Class<A> type) {...}
And the caller of that method would be able to use the returned object as either type:
final Foo foo = makeSomeClass(Foo.class);
final SomeClass someClass = foo.asSomeClass();
If the interfaces themselves can't be modified, then another option is to use a wrapper class and composition instead:
final class SomeClassWrapper<A> {
private final SomeClass someClass;
private final A a;
//constructor and getters, etc.
}
And your method would return a wrapper instance instead, assigning the implementation instance to both someClass and a:
public static <A> SomeClassWrapper<A> makeSomeClass(Class<A> type) {...}
If SomeClass is always a class, the A in <B extends SomeClass & A> can only be an interface, because there is no multiple inheritance in Java. The only way & A can be satisfied is if A is an interface.
I think the problem here is that you want to return a B from this method.
You specify B as a type parameter, but it never appears anywhere else in the method signature.
How is the compiler supposed to infer the return type from the arguments????
There is no opportunity for the client code to specify what B is.
It seems like you should return either a SomeClass or an A.
Either one can be a B under the hood, but should appear as a SomeClass or an A to the client code.