I would like to create a generic interface for those two classes but I'm not sure how to specify the generics the right way.
public class ThingA implements Thing {
public ThingA createCopy(ThingA original);
}
public class ThingB implements Thing {
public ThingB createCopy(ThingB original);
}
I tried it this.
public interface Thing<V extends Thing<V>> {
public V createCopy(V original);
}
But I'm still able to do things like this, which shouldn't be allowed.
public class ThingB implements Thing<ThingA> {
public ThingA createCopy(ThingA original);
}
There is no this key-word generics (nor for methods parameters and return values declaration) and thus you cannot do exactly what you want.
In other words the interface will permit to ensure all the methods in the class use consistent types, but not to reference the class type itself.
This is not possible. And it is not what Generics is for. Generics is for type safety, i.e. avoiding casts. If someone makes a class ThingB that implements Thing<ThingA> somehow, then great. It is perfectly type-safe. Why do you care? How does it impede what you are doing?
Are you looking for
public interface Thing<V> {
public V createCopy(V original);
}
? If not, can you explain in more detail what it means to you to "create a generic interface for two classes"?
In case you are free to use extension instead of implementation, then you could do that this way:
public interface Thing { ... }
public abstract class Copyable {
public final Copyable copy() {
Copyable clone = createCopy();
if (clone.getClass() != getClass())
throw new RuntimeException("Copy has wrong type!");
return clone;
}
protected abstract Copyable createCopy();
}
And then use it like:
public class Test extends Copyable implements Thing {
public String content = null;
#Override
public Copyable createCopy() {
Test clone = new Test();
clone.content = this.content;
return clone;
}
}
/*code somewhere*/ {
Test t1 = new Test();
t1.content = "Hello world!";
Test t2 = (Test)t1.copy();
System.out.println(t2.content);
}
One problem with this, is that Copyable is not an interface. However, this can be used without much pain, as seen in the example, but the class checking used is not supported on the language level. With other words, the createCopy abstract method is not restricted to the class it copies, and all that is up to the programmer who extends the Copyable class, or a class, which extends it.
The positive side, is that if you call the .copy() on the object, it must return an object same as itself. Instead of an exception you can return null, if you want. Then you got good or nothing.
But, to be honest, I don't really understand, why your createCopy local method has a parameter.
It could be then a static method ... altrough I cannot even imagine what would go into that code block:
static <X extends Thing> X copy(X object) { ... }
May you could combine the pratice with a static generic method and the result becomes a bit more friendly:
public interface Thing extends Cloneable {
public static <X extends Thing> X copy(X thing) {
Object clone = thing.clone();
if (clone.getClass() != getClass())
throw new RuntimeException("Copy has wrong type!");
return (X)clone;
}
}
public class ThingA implements Thing {
public Object clone() { ... }
}
/*code somewhere*/ {
ThingA a1 = new ThingA();
ThingA a2 = Thing.copy(a1);
}
Still, the cloning method is regulated by an exception instead of language restriction, but I think this is far the best solution.
Related
How can i make an interface in java with a function that accepts a parameter of the type that extends the interface?
For example take the interface ISelfComparable
if class A extends it then i would expect it to implement
bool compareTo(A other)
but if class B extends it then i would expect it to implement
bool compareTo(B other)
I know i can use a generic interface but it seems incorrect because it doesn't make any sense for A to extend ISelfComparable<B>
If this is impossible, what is the best practice in this kind of situation?
The usual solution is self-bounded generics, as seen in the Enum class.
interface Example<T extends Example<T>> {
void foo(T t);
}
public class ExampleImpl implements Example<ExampleImpl> {
#Override
public void foo(ExampleImpl example) {
}
}
How it works is a bit dizzying, but is explained very well here for example. There is also a very good answer on the subject here.
Note that it isn't foolproof, as it allows this:
public class ExampleImpl2 extends Example<ExampleImpl {
#Override
public void foo(ExampleImpl example) {
}
}
But in practice the self-bounded idiom is used to express exactly the sort of thing you're after.
If you really, really, really need the parameter object to always be the exact same class as this, you have to do a runtime check. (It also raises the question of why you need this, but that would take us way off topic.)
Have a look at the class java.lang.Comparable: it has an argument with the type of the objects that can be used int compareTo.
By analogy:
public interface ISelfComparable<T extends ISelfComparable<T>> {
boolean compareTo(T other);
}
There is a way to check the type of parameter but only in runtime. For example you can implement type checking in default method:
interface ISelfComparable {
default boolean compareTo(ISelfComparable param) {
if (this.getClass() != param.getClass()) {
throw new IllegalArgumentException();
}
...
}
}
Then each implementation of this interface should look like this:
class A implements ISelfComparable {
#Override
public boolean compareTo(ISelfComparable param) {
ISelfComparable.super.compareTo(param);
...
}
}
In this case if you call new A().compareTo(new B()); then java.lang.IllegalArgumentException will be thrown
I know there's many similar question but I had no luck finding a nice and clean solution if it's possible at all.
I'm implementing a generic interface with subclasses of an abstract type. Problem is that when I'm calling them I either must do type cast in a switch/case or cast type in every method inside interface implementations and I can't figure out a nice and clean approach... I'll better just write down a short example.
// An abstract type with 2 implementations...
public abstract class ObjTypeAbstract {}
public class ObjType extends ObjTypeAbstract {}
public class ScriptType extends ObjTypeAbstract {}
Now the processor for both types with an interface
interface ProcessorInterface<T extends ObjTypeAbstract> {
public void abcMethod(T obj);
}
public class ObjProcessor implements ProcessorInterface<ObjType> {
public void abcMethod(ObjType obj) {}
}
public class ScriptProcessor implements ProcessorInterface<ScriptType> {
public void abcMethod(ScriptType obj) {}
}
What I'm struggling with is a way of calling those processors based on ObjAbstractType. I have a single class that servers as middleware?? or how should I call it.:
Idea was to simple get the right processor via a single switch/case:
public class Processor {
private ProcessorInterface objProcessor = new ObjProcessor();
private ProcessorInterface scriptProcessor = new ScriptProcessor();
public methodAbc(ObjAbstractType obj) {
getProcessor(obj).abcMethod(obj);
}
private ProcessorInterface getProcessor(ObjAbstractType obj) {
if (obj instanceof ObjType) {
return objectProcessor;
} else if (obj instanceof ScriptType) {
return scriptProcessor;
}
return nullProcessor;
}
}
This is what I'd like to have, it also takes care of type casting of objAbstract to actual type for abcMethod, problem is that it results in RawType warning which won't break the code, but I'd like to get rid of it.
And thats where I'm stuck... because if I cast processors to specific type like this:
private ProcessorInterface<ObjType> objProcessor = new ObjProcessor();
private ProcessorInterface<ScriptType> scriptProcessor = new ScriptProcessor();
I won't be able to return an abstract one from getProcessor method so I would have to implement those interfaces with an ObjAbstractType with all it's method and have type casting in all methods of every processor like:
public class ScriptProcessor implements ProcessorInterface<ObjAbstractType> {
public void abcMethod(ObjAbstractType obj) {
ScriptType scr = (ScriptType) obj;
}
}
The other solution might be having a switch/case inside Processor middleware class and cast ObjAbstractType in it, but I'd have to write that switch inside abcMethod and all others or from getProcessor method returns both the Processor and casted ObjType... so I'd have to return some dto containing both. :/
Do you have any ideas / patterns that might help me to get rid of RawType call warning without extending the code with more switch/case or type casts?
Wish you a nice day and I'll be glad for any discussion, David.
You need a way to store the mapping between a ObjTypeAbstract class and a ProcessorInterface instance.
You could use a Map that associates ObjTypeAbstracts (as key) to ProcessorInterfaces (as value).
About the raw type issue, you could use ProcessorInterface<? extends ObjTypeAbstract> for the declared variable but you will still need to perform a unsafe cast to ProcessorInterface<ObjTypeAbstract> to be able to invoke ProcessorInterface.abcMethod() with as parameter a ObjTypeAbstract declared type.
This cast is unavoidable with your actual design.
It could give something like :
public class Processor {
private Map<Class<? extends ObjTypeAbstract>, ProcessorInterface<? extends ObjTypeAbstract >> map = new HashMap<>();
public Processor(){
map.put(ObjType.class, new ObjProcessor());
map.put(ScriptType.class, new ScriptProcessor());
}
public void methodAbc(ObjTypeAbstract obj) {
#SuppressWarnings("unchecked")
ProcessorInterface<ObjTypeAbstract> processorInterface = (ProcessorInterface<ObjTypeAbstract>) map.get(obj.getClass());
processorInterface.abcMethod(obj);
}
}
I don't think there is a substantially more elegant way to get around some form of instanceof logic. However, there should not be need for casting, if you add some types to getProcessor.
public <T extends ObjTypeAbstract> ProcessorInterface<T> getProcessor(Class<T> theClass) {
if (theClass.isAssignableFrom(ObjType.class)) {
return objProcessor;
} else if (theClass.isAssignableFrom(ScriptType.class)) {
return scriptProcessor;
}
return null;
}
This can then be called like this:
ProcessorInterface<ScriptType> scriptProcessor = new Processor().getProcessor(ScriptType.class);
ProcessorInterface<ObjType> objProcessor = new Processor().getProcessor(ObjType.class);
So, let's say we have a simple interface
public interface ICopyable<T> {
void copyFrom(T original);
}
Which basically adds a copyFrom method with a parameterized type. And you have an interface extending it:
public interface ISomeObject<T> extends ICopyable<T> {
String getType();
}
The interface isn't adding anything valuable of course apart of it's type, but let's pretend there are some useful methods in it. The idea is still the same - all objects of this interface have a getType() method and they can copy one object of THE SAME TYPE from one to the other.
Now let's have two implementations of this interface, and the second implementation inherits from the first one:
public static class ActualObject1 implements ISomeObject<ActualObject1> {
Object data1;
#Override public void copyFrom(final ActualObject1 original) {
this.data1 = original.data1;
}
#Override public String getType() {
return this.getClass().getSimpleName();
}
}
public static class ActualObject2 extends ActualObject1 {
Object data2;
#Override public void copyFrom(final ActualObject1 original) {
super.copyFrom(original);
// oh no! i've just realized that i'm not copying the ActualObject2!
}
}
So the second's object(ActualObject2) is supposed to extend the ActualObject1, but if it's done this way it can't implement the right "copyFrom" method, as the first class implements the interface ISomeObject for itself only. And it obviously wants to do it somehow to allow copying of ActualObject2's to each other. But how?
It can't just declare implements ISomeObject as it'll clash with it's parent's implementation type.
So you'll want to do something like that maybe?
public static class ActualObject1<T extends ActualObject1> implements ISomeObject<T> {
Object data1;
#Override public void copyFrom(final ActualObject1 original) {
this.data1 = original.data1;
}
#Override public String getType() {
return this.getClass().getSimpleName();
}
}
public static class ActualObject2 extends ActualObject1<ActualObject2> {
Object data2;
#Override public void copyFrom(final ActualObject2 original) {
super.copyFrom(original);
this.data2 = original.data2;
}
}
Basically parameterizing the class1, and class2 specifies itself as a parameter. It all works fine, you can create instances of both types:
ActualObject1 obj1 = new ActualObject1();
However there's one "little" problem - the obj1 has a raw type. The full declaration looks rather silly:
ActualObject1<ActualObject1> obj2 = new ActualObject1<>();
But it works. However the "raw type" nature of this class can bite for example in this scanario:
public static class SomeOtherParameterizedClass<T extends ISomeObject<T>> {
void copyObjects(T obj1, T obj2) {
obj1.copyFrom(obj2);
}
}
So you're creating some random class parameterized by <T extends ISomeObject<T>>. And you can in theory say it like that: <T extends ISomeObject> but then you won't be able to use T in the "copyFrom" safely. In other words - it's a valid class parameterization, it has a point.
But then you can't parameterize it for ActualObject1:
SomeOtherParameterizedClass<ActualObject1> a1 = new SomeOtherParameterizedClass<>();
Yea - doesn't work. Hint:
SomeOtherParameterizedClass<ActualObject2> a2 = new SomeOtherParameterizedClass<>();
Works just fine...
So what's the right approach here? I'm more interested in retaining the type safety as much as possible, as for sure you can just use raw types all the way and don't worry about anything, but it's for the weak! :-)
We're in statically typed language so it's somewhat of an academic question - what's the right way of designing this class hierarchies with generics? Is occasionally using raw-types actually required for those to work?
I came to a problem with interfaces in a program I'm making. I want to create a interface which have one of its methods receiving/returning a reference to the type of the own object. It was something like:
public interface I {
? getSelf();
}
public class A implements I {
A getSelf() {
return this;
}
}
public class B implements I {
B getSelf() {
return this;
}
}
I can't use an "I" where it's a "?", because I don't want to return a reference to the interface, but the class. I searched and found that there are no way to "self-refer" in Java, so I can't just substitute that "?" in the example for a "self" keyword or something like this. Actually, I came up to a solution that goes like
public interface I<SELF> {
SELF getSelf();
}
public class A implements I<A> {
A getSelf() {
return this;
}
}
public class B implements I<B> {
B getSelf() {
return this;
}
}
But it really seems like a workaround or something alike. Is there another way to do so?
There is a way to enforce using ones own class as a parameter when extending an interface:
interface I<SELF extends I<SELF>> {
SELF getSelf();
}
class A implements I<A> {
A getSelf() {
return this;
}
}
class B implements I<A> { // illegal: Bound mismatch
A getSelf() {
return this;
}
}
This even works when writing generic classes. Only drawback: one has to cast this to SELF.
As Andrey Makarov noted in a comment below this does not work reliably when writing generic classes.
class A<SELF extends A<SELF>> {
SELF getSelf() {
return (SELF)this;
}
}
class C extends A<B> {} // Does not fail.
// C myC = new C();
// B myB = myC.getSelf(); // <-- ClassCastException
Java supports covariant return types, so that's one option. Take advantage of the fact that both A and B are derived from Object:
public interface I {
Object getSelf(); // or I, see below
}
public class A implements I {
A getSelf() { return this; }
}
public class B implements I {
B getSelf() { return this; }
}
The point is that both A.getSelf() and B.getSelf() are legitimate overrides of I.getSelf(), even though their return type is different. That's because every A can be treated like an Object, and so the return type is compatible with that of the base function. (This is called "covariance".)
In fact, since A and B are also known to derive from I, you can replace Object by I for the same reasons.
Covariance is generally a Good Thing: Someone who has an interface object of type I can call getSelf() and get another interface, and that's all she needs to know. On the other hand, someone who already knows he has an A object can call getSelf() and will actually get another A object back. The additional information can be used to get a more specific derived type, but someone who lacks that information still gets everything that's prescribed by the interface base class:
I x = new A();
A y = new A();
I a = x.foo(); // generic
A b = y.foo(); // we have more information, but b also "is-an" I
A c = (A)x.foo(); // "cheating" (we know the actual type)
I was wondering if there are any other way to do so?
You can write it as follows:
public interface I {
I getSelf();
}
and then cast the result to the type you want. Your existing A and B classes will work as-is.
(This is an example of return type covariance. Support for return type covariance was added in Java 5. This approach will give compilation errors in older JDKs.)
The alternative version (you call it a work-around, but it isn't really) that uses generics allows you to avoid the explicit typecast. However, there is an implicit typecast in the generated code, and at runtime ... unless the JIT compiler can optimize it away.
There are no better alternatives, AFAIK.
As others have said, you can override the return type in the implementing classes:
public interface I {
public I getSelf();
}
public class A implements I {
#Override
public A getSelf() {
return this;
}
}
However, I have two 'why' questions for you:
1: Why do you want an Interface to return the implementing object? It seems to run against the general ideas of interfaces and inheritance to me. Can you show an example of how this might be used?
2: In any case, why would you want this function? If a.getSelf() == a, why not just use a?
I came to a problem with interfaces in a program I'm making. I want to create a interface which have one of its methods receiving/returning a reference to the type of the own object. It was something like:
public interface I {
? getSelf();
}
public class A implements I {
A getSelf() {
return this;
}
}
public class B implements I {
B getSelf() {
return this;
}
}
I can't use an "I" where it's a "?", because I don't want to return a reference to the interface, but the class. I searched and found that there are no way to "self-refer" in Java, so I can't just substitute that "?" in the example for a "self" keyword or something like this. Actually, I came up to a solution that goes like
public interface I<SELF> {
SELF getSelf();
}
public class A implements I<A> {
A getSelf() {
return this;
}
}
public class B implements I<B> {
B getSelf() {
return this;
}
}
But it really seems like a workaround or something alike. Is there another way to do so?
There is a way to enforce using ones own class as a parameter when extending an interface:
interface I<SELF extends I<SELF>> {
SELF getSelf();
}
class A implements I<A> {
A getSelf() {
return this;
}
}
class B implements I<A> { // illegal: Bound mismatch
A getSelf() {
return this;
}
}
This even works when writing generic classes. Only drawback: one has to cast this to SELF.
As Andrey Makarov noted in a comment below this does not work reliably when writing generic classes.
class A<SELF extends A<SELF>> {
SELF getSelf() {
return (SELF)this;
}
}
class C extends A<B> {} // Does not fail.
// C myC = new C();
// B myB = myC.getSelf(); // <-- ClassCastException
Java supports covariant return types, so that's one option. Take advantage of the fact that both A and B are derived from Object:
public interface I {
Object getSelf(); // or I, see below
}
public class A implements I {
A getSelf() { return this; }
}
public class B implements I {
B getSelf() { return this; }
}
The point is that both A.getSelf() and B.getSelf() are legitimate overrides of I.getSelf(), even though their return type is different. That's because every A can be treated like an Object, and so the return type is compatible with that of the base function. (This is called "covariance".)
In fact, since A and B are also known to derive from I, you can replace Object by I for the same reasons.
Covariance is generally a Good Thing: Someone who has an interface object of type I can call getSelf() and get another interface, and that's all she needs to know. On the other hand, someone who already knows he has an A object can call getSelf() and will actually get another A object back. The additional information can be used to get a more specific derived type, but someone who lacks that information still gets everything that's prescribed by the interface base class:
I x = new A();
A y = new A();
I a = x.foo(); // generic
A b = y.foo(); // we have more information, but b also "is-an" I
A c = (A)x.foo(); // "cheating" (we know the actual type)
I was wondering if there are any other way to do so?
You can write it as follows:
public interface I {
I getSelf();
}
and then cast the result to the type you want. Your existing A and B classes will work as-is.
(This is an example of return type covariance. Support for return type covariance was added in Java 5. This approach will give compilation errors in older JDKs.)
The alternative version (you call it a work-around, but it isn't really) that uses generics allows you to avoid the explicit typecast. However, there is an implicit typecast in the generated code, and at runtime ... unless the JIT compiler can optimize it away.
There are no better alternatives, AFAIK.
As others have said, you can override the return type in the implementing classes:
public interface I {
public I getSelf();
}
public class A implements I {
#Override
public A getSelf() {
return this;
}
}
However, I have two 'why' questions for you:
1: Why do you want an Interface to return the implementing object? It seems to run against the general ideas of interfaces and inheritance to me. Can you show an example of how this might be used?
2: In any case, why would you want this function? If a.getSelf() == a, why not just use a?