I am creating a game where objects implement interfaces for animations. I have a parent interface for the animations. Here is a shortened version:
public interface Animates<S extends Animator> {
S createAnimator(long animationTime);
}
In addition, I have multiple interfaces that extend this interface. Two examples:
public interface AnimatesPaint extends Animates<PaintAnimator> {
PaintAnimator createPaintAnimator(long animationTime);
default PaintAnimator createAnimator(long animationTime) {
return createPaintAnimator(animationTime);
}
}
and
public interface AnimatesPosition extends Animates<PositionAnimator> {
PositionAnimator createPositionAnimator(long animationTime);
@Override
default PositionAnimator createAnimator(long animationTime) {
return createPositionAnimator(animationTime);
}
}
As you can see, the interfaces that extend Animates
override the createAnimator
method in order to delegate the logic of createAnimator
to the class that implements the interface.
The reason I am doing this is that I want to be able to have a screen element (that can animate) that implements multiple animation interfaces (for example both AnimatesPosition
to move the element around and AnimatesPaint
to change its color).
However, that apparently does not work. When I implement both in one class (illustrated below), I get the compilation error:
createAnimator(long) in AnimatesPaint clashes with createAnimator(long) in AnimatesPosition; attempting to use incompatible return types
Here is an example of a class that implements both Animates interfaces:
public class ScreenElement implements AnimatesPaint, AnimatesPosition {
@Override
PositionAnimator createPositionAnimator(long animationTime) {
return new PositionAnimator(animationTime);
}
@Override
PaintAnimator createPaintAnimator(long animationTime) {
return new PaintAnimator(animationTime);
}
}
So what I don't understand is that both AnimatesPaint
and AnimatesPosition
already implement createAnimator
. Yet, the error message seems to suggest that createAnimator
also needs to be implemented by ScreenElement
! If createAnimator
would not have been implemented yet, I would get it, why there is a clash.
Where does my logic go wrong?
In the end, what I want to achieve, is to have a generic method that can initiate any type of animation. For example:
public class AnimationStarter<S extends Animates, T> {
public void startAnimation(S animates, T start, T target, long animationTime) {
Animator animator = animates.createAnimator(animationTime);
animator.init(start, target);
animates.setAnimator(animator);
animator.startAnimation();
}
}
--Edit--
Upon request, here is the declaration of Animator
public abstract class Animator<T> {}
and one of its extended classes
public class PositionAnimator extends Animator<Point>{}
A class can implement any number of interfaces. In this case there is no ambiguity even though both the interfaces are having same method. Because methods in an interface are always abstract by default, which doesn’t let them give their implementation in interface itself. Are there any code examples left?
Why an interface cannot implement another interface in Java? An interface cannot implement another interface in Java. An interface in Java is essentially a special kind of class. Like classes, the interface contains methods and variables. Unlike classes, interfaces are always completely abstract.
An interface extends another interface because the interface that extends another interface just adds its own abstract method (s) and doesn’t provide method definitions for abstract methods of the other interface. An interface will never extend a class as interfaces don’t provide method definitions.
Creating an interface is a good way of grouping related functionalities. There are times when you need to bring related functionalities together into one class. being able to implement multiple interfaces gives you that flexibility.
So what I don't understand is that both
AnimatesPaint
andAnimatesPosition
already implementcreateAnimator
.
Yes, and those implementations conflict with one another. If you could do this, your resulting class's type would need to expose two createAnimator
methods that are only differentiated by return type. Java doesn't let you have overloads that are only differentiated by return type, so you can't do that. A method signature, for overloading purposes, doesn't include the return type.
Even if they had the same return type (Animator
), you'd then have two overloads with exactly the same signature, which you can't do.
They'll need to be separate methods — e.g., with separate signatures that can be differentiated — if they're going to be implemented in the same class.
In a comment you've asked:
But isn't the conflict resolved by the fact that the method has already been overriden by
AnimatesPaint
andAnimatesPosition
? This way the implementing classScreenElement
doesn't need to implementcreateAnimator
method, so no conflict will occur.
No, because the class itself exposes those methods (or rather, would need to) as part of its signature. Basically, suppose you could create the class and you had an instance of it, s
. What would s.createAnimator(300L)
do? Which one should the compiler choose?
A class's public type is composed of all of its public members, including all the public members of all of the interfaces it implements. So at a type level, it's impossible for two interfaces to implement methods with the same signature.
If you call ScreenElements createAnimator() method, which one is it supposed to use? That’s what the compiler is complaining about. You need to tell it what to do when that method is called. Based on the code I’m not sure. So you are correct that ScreenElement needs to implement the create animator method, that way the compiler knows what to do when that method is called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With