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?
Related
I am going over some code and I am adding some interfaces so i can make sure all the classes follow the same basic guidelines.
Now I have an interface called Uni < T > which takes exactly one generic argument.
Say I have a class which implements Uni< Foo > then I would like that class to have this method public foo getFoo(){};
Is there any way to add this method to the interface? I would prefer if i could do something like this in my interface public T getT(); and the second T gets replaced by the generic argument.
I can't just call it "get" because I would like some classes to implement multiple versions of Uni. public Example implements Uni<Foo1>,Uni<Foo2>
I know I can give the function 'get' an argument Foo or Class but I'd rather not so I thought I'd ask here.
(I would also mess up the naming convection if i did this)
No, not possible. And as generics in Java are implemented via erasure (i.e. dropped by the compiler), you will also not be able to implement multiple versions in a single class.
its not possible with java but you can do it like this
public interface example<T> {
public void yourmethod(T object);
}
make the interface according to the generic type you want.
It seems like you usually implemented the java.lang.Comparable interface without specifying the type parameter.
public abstract class Area implements Comparable {
#Override
public int compareTo(Object other) {
if (other instanceof Area)
return new Double(getArea()).compareTo(other.getArea());
return -1; // or something else
}
abstract public double getArea();
}
Since I only want to compare apples with apples, I think it would make sense to specify the type.
public abstract class Area implements Comparable<Area> {
#Override
public int compareTo(Area other) {
// ...
If I want to introduce another class to compare Area with, I thought I could do the following:
public abstract class Area implements Comparable<Area>, Comparable<Volume> {
#Override
public int compareTo(Area other) {
// ...
}
#Override
public int compareTo(Volume other) {
// ...
}
}
But the java compiler tells me:
Area.java:2: error: repeated interface
public abstract class Area implements Comparable<Area>, Comparable<Volume> {
^
Area.java:2: error: Comparable cannot be inherited with different arguments: <Area> and <Volume>
Are there any drawbacks specifying the type argument for the generic interface?
Why won't Java allow me this multiple implementation?
Note: I'm using Java version 1.7.0_45
No, it's not a drawback of specifying the generic - it's actually a feature. Also, I don't recall any drawback for using generics in interfaces, other than the well-known fact you can't instantiate a generic type nor create a generic array (but that's more a problem of implementation, not the interface itself).
It's due to type erasure. Comparable<Area> and Comparable<Volume> is essentially the same class for the VM, and, shortly after checking validity, also for compiler.
If you want to have two distinct comparable interfaces implemented, just use Comparators for them - it's generally easier to maintain composition than inheritance in classes.
For some applications (distinguishing generics at run-time) you may also try subclassing them, e.g. ComparableArea extends Comparable<Area> & ComparableVolume extends Comparable<Volume>, but that would, in this particular case, cause more trouble than it would solve IMO, since you'd still get Comparable cannot be inherited with different arguments error - but at least you could differentiate those interfaces by e.g. instanceof.
I think this way java is saying that related classes can be Comparable, but using artificial Comparator we can do more comparisons among unrelated classes.
So we should implement generic interface of related classes (classes within the same inheritance hierarchy). In case we want to add an artificial implementation, add an interface which can be passed through (so have pair of family of interfaces like Comparable and Comparator).
is it possible in Java to let a class extend a generic type, so that you can inject an method into any class passed through your code? (Or is there any other way to inject or override methods into an existing class with Java?)
What I mean with "extend a generic type" is something like this (Class "T extends GameObject" belongs to game and may not be changed AND is unknown because loaded into the game at runtime (from other mods)):
class GameObject {
void moveForward(float amount) {
this.camera.z += amount;
}
}
class Extender<T extends GameObject> extends T {
void onTick(float time) {
this.camera.z -= amount;
}
}
onTick is called by the GameEngine, and in this way I could replace every existing game object with a version that moves backwards on every tick.
No. You cannot extend a generic supertype. You can extend classes that make use of generic types (e.g. public class MyClass<T> extends TheirClass<T>) but you cannot extend a purely generic type.
In my opinion you can find the solution not in language's features, but in some design pattern, as Decorator or Template Method Pattern.
If the behaviour is determinated in runtime, you could give a look at behaviour patterns.
I'd like to use define a generic class in java, that can only be instantiated using my custom data types that all share the same base class. Is it possible to do so without checking the datatype at runtime? Furthermore I'd like to prohibit instantiating a generic class without providing a datatype.
Edit:
I writing a java wrapper for my c++ library and therefore the java class should only allow wrapper classes for my c++ datatypes as parameters. I just tried using bounded type parameters, as suggested, but then I can still instantiate an object like this:
MyClass c = new MyClass();
This is basically the code:
public class MyClass<T extends MyType>
{
public MyClass()
{
}
public doSomething(MyOtherClass<T> other)
{
}
}
What you are looking for is called Bounded Type Parameters:
There may be times when you'll want to restrict the kinds of types that are allowed to be passed to a type parameter. For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for.
public <U extends Number> void inspect(U u){
System.out.println("T: " + t.getClass().getName());
System.out.println("U: " + u.getClass().getName());
}
Due to type erasure -- and the now very old requirement for backwards-compatibility -- there is no way to require that a class is instantiated with generic type parameters. Two solutions:
Heed the warnings. Let the developers who don't feel the wrath of run-time exceptions :-)
Only allow access through classes that extend the generic class (and provide type parameters). For instance, class MyClassFoo extends MyClass<Foo> and then hide the MyClass constructor from external code.
Neither is ideal, but it is what it is. Both C++ and .NET work differently, but then again they are C++/.NET and not Java :-)
Happy coding.
If you're worried about others creating their own subclass of your base class and using this in your generic type, the only way you can prohibit this is to control extension to your base class.
One way is to protect the base class's constructor using default visibility and put the concrete implementations in the same class. Make those concrete implementations final, or make their constructors private.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
java Enum definition
Better formulated question, that is not considered a duplicate:
What would be different in Java if Enum declaration didn't have the recursive part
if language designers were to use simply Enum<E extends Enum> how would that affect the language?
The only difference now would be that someone coud write
A extends Enum<B>
but since it is not allowed in java to extend enums that would be still illegal.
I was also thinking about someone supplying jvm a bytecode that defines smth as extending an enum - but generics can't affect that as they all are erased.
So what is the whole point of such declaration?
Thank you!
Edit
for simplicity let's look at an example:
interface MyComparable<T> {
int myCompare(T o);
}
class MyEnum<E extends MyEnum> implements MyComparable<E> {
public int myCompare(E o) { return -1; }
}
class FirstEnum extends MyEnum<FirstEnum> {}
class SecondEnum extends MyEnum<SecondEnum> {}
what's wrong with this class structure? What can be done that "MyEnum<E extends MyEnum<E>>" would restrict?
This is a common question, and understandably so. Have a look at this part of the generics FAQ for the answer (and actually, read as much of the whole document as you feel comfortable with, it's rather well done and informative).
The short answer is that it forces the class to be parameterized on itself; this is required for superclasses to define methods, using the generic parameter, that work transparently ("natively", if you will) with their subclasses.
Edit: As a (non-)example for instance, consider the clone() method on Object. Currently, it's defined to return a value of type Object. Thanks to covariant return types, specific subclasses can (and often do) define that they return a more specific class, but this cannot be enforced and hence cannot be inferred for an arbitrary class.
Now, if Object were defined like Enum, i.e. Object<T extends Object<T>> then you'd have to define all classes as something like public class MyFoo<MyFoo>. Consequently, clone() could be declared to return a type of T and you can ensure at compile time that the returned value is always exactly the same class as the object itself (not even subclasses would match the parameters).
Now in this case, Object isn't parameterized like this because it would be extremely annoying to have this baggage on all classes when 99% of them aren't going to utilise it at all. But for some class hierarchies it can be very useful - I've used a similar technique myself before with types of abstract, recursive expression parsers with several implementations. This construct made it possible to write code that was "obvious" without having to cast everywhere, or copy-and-paste just to change concrete class definitions.
Edit 2 (To actually answer your question!):
If Enum was defined as Enum<E extends Enum>, then as you rightly say, someone could define a class as A extends Enum<B>. This defeats the point of the generic construct, which is to ensure that the generic parameter is always the exact type of the class in question. Giving a concrete example, Enum declares its compareTo method as
public final int compareTo(E o)
In this case, since you defined A to extend Enum<B>, instances of A could only be compared against instances of B (whatever B is), which is almost certainly not very useful. With the additional construct, you know that any class that extends Enum is comparable only against itself. And hence you can provide method implementations in the superclass that remain useful, and specific, in all subclasses.
(Without this recursive generics trick, the only other option would be to define compareTo as public final int compareTo(Enum o). This is not really the same thing, as then one could compare a java.math.RoundingMode against a java.lang.Thread.State without the compiler complaining, which again isn't very useful.)
OK, let's get away from Enum itself as we appear to be getting hung up on it. Instead, here is an abstract class:
public abstract class Manipulator<T extends Manipulator<T>>
{
/**
* This method actually does the work, whatever that is
*/
public abstract void manipulate(DomainObject o);
/**
* This creates a child that can be used for divide and conquer-y stuff
*/
public T createChild()
{
// Some really useful implementation here based on
// state contained in this class
}
}
We are going to have several concrete implementations of this - SaveToDatabaseManipulator, SpellCheckingManipulator, whatever. Additionally we also want to let people define their own, as this is a super-useful class. ;-)
Now - you will notice that we're using the recursive generic definition, and then returning T from the createChild method. This means that:
1) We know and the compiler knows that if I call:
SpellCheckingManipulator obj = ...; // We have a reference somehow
return obj.createChild();
then the returned value is definitely a SpellCheckingManipulator, even though it's using the definition from the superclass. The recursive generics here allow the compiler to know what is obvious to us, so you don't have to keep casting the return values (like you often have to do with clone(), for example).
2) Notice that I didn't declare the method final, since perhaps some specific subclasses will want to override it with a more suitable version for themselves. The generics definition means that regardless of who create a new class or how it is defined, we can still assert that the return from e.g. BrandNewSloppilyCodedManipulator.createChild() will still be an instance of BrandNewSloppilyCodedManipulator. If a careless developer tries to define it to return just Manipulator, the compiler won't let them. And if they try to define the class as BrandNewSloppilyCodedManipulator<SpellCheckingManipulator>, it won't let them either.
Basically, the conclusion is that this trick is useful when you want to provide some functionality in a superclass that somehow gets more specific in subclasses. By declaring the superclass like this, you are locking down the generic parameter for any subclasses to be the subclass itself. This is why you can write a generic compareTo or createChild method in the superclass and prevent it from becoming overly vague when you're dealing with specific subclasses.