Why can't I implement multiple interfaces?

MWB :

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>{}
T.J. Crowder :

So what I don't understand is that both AnimatesPaint and AnimatesPosition already implement createAnimator.

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 and AnimatesPosition? This way the implementing class ScreenElement doesn't need to implement createAnimator 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.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=304664&siteId=1