简体   繁体   中英

Java: How can I make a ball behave as a bouncing and elastic ball?

I have two classes BouncingBall and another one called ElasticBall . Both classes extends BallImpl which implements an interface called Ball .

public interface Ball {
    int DEFAULT_RADIUS = 50;

    int radius();
    Point center();
    void update();
}

public class BouncingBall extends BallImpl {
    public static final int MOVEMENT_SPEED = 12;

    static final int DOWN = 1;
    static final int UP = -1;

    private int direction;

    BouncingBall(int x, int y, int direction) {
        super(x, y);
        this.direction = direction;
    }

    @Override
    public void update() {
        direction = reverseDirectionIfNecessary();
        y = move();
    }

    private int reverseDirectionIfNecessary() {
        if (movingTooHigh() || movingTooLow()) {
            return switchDirection();
        }

        return this.direction;
    }

    private boolean movingTooLow() {
        return y + radius >= BallWorld.BOX_HEIGHT && movingDown();
    }

    private boolean movingTooHigh() {
        return y - radius <= 0 && movingUp();
    }

    private int switchDirection() {
        return movingDown() ? UP : DOWN;
    }

    private int move() {
        return y + (MOVEMENT_SPEED * direction);
    }

    private boolean movingDown() {
        return direction == DOWN;
    }

    private boolean movingUp() {
        return direction == UP;
    }
}

public class ElasticBall extends BallImpl {
    public static final int GROWTH_RATE = 2;

    static final int GROW = 1;
    static final int SHRINK = -1;

    private int growthDirection;

    ElasticBall(int x, int y, int radius, int growthDirection) {
        super(x, y, radius);
        this.growthDirection = growthDirection;
    }

    @Override
    public void update() {
        growthDirection = reverseGrowthDirectionIfNecessary();
        radius = next();
    }

    private int reverseGrowthDirectionIfNecessary() {
        if (growingTooBig() || shrinkingTooSmall()) {
            return switchDirection();
        }

        return this.growthDirection;
    }

    private boolean shrinkingTooSmall() {
        return radius <= 0 && shrinking();
    }

    private boolean growingTooBig() {
        return radius >= Ball.DEFAULT_RADIUS && growing();
    }

    private int switchDirection() {
        return growing() ? SHRINK : GROW;
    }

    private int next() {
        return radius + (GROWTH_RATE * growthDirection);
    }

    private boolean shrinking() {
        return growthDirection == SHRINK;
    }

    private boolean growing() {
        return growthDirection == GROW;
    }
}

I need to create a BouncingElasticBall which combines the behavior of the BouncingBall and the ElasticBall classes. I have poor knowledge in OOP, and I know Java does not allow multiple inheritance, so how can I solve this problem?

Thanks in advance.

One way you could approach this is to not extend BallImpl , but make sort-of plugins . Like this:

public class BallImpl implements Ball {
    List<BallBehavior> behaviors = ...

    @Override
    public void update() {
       behaviors.forEach(behavior -> behavior.update(this));
    }
    ...
}

public interface BallBehavior {
    void update(BallImpl ballImpl);
}

And then, just write your elastic and bouncing logic as behaviors .

Once you diverge hierarchies there's no way to merge them in java.

It's a design matter: if you know that ElasticBall and BouncingBall may be combined together, you should create two interfaces Elastic and Bouncing , both extending interface Ball , with common methods valid for both.

Then the common method implementations may be set into a common abstract class, let's say AbstractBall . At this point you can finally detail your three implementations:

  • ElasticBall extends AbstractBall implements Elastic
  • BouncingBall extendis AbstractBall implements Bouncing
  • ElasticBouncingBall extends AbstractBall implements Elastic, Bouncing

In this way you'll be able to control what to do in each method, reuse code for common stuff (in the abstract class).

You can use interfaces that allows multiple inheritance. Make the interface for each ball ElasticBall and BouncingBall and implement both of them in BouncingElasticBall .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM