我有两个班BouncingBall
,另一个班叫ElasticBall
。这两个类都扩展了BallImpl
,它实现了一个名为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;
}
}
我需要创建一个BouncingElasticBall
,它结合了BouncingBall
和ElasticBall
类的行为。我对OOP知之甚少,而且我知道Java不允许多重继承,那么我该如何解决这个问题?
提前致谢。
答案 0 :(得分:6)
您可以采用的一种方法是不扩展 BallImpl
,而是制作排序插件。像这样:
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);
}
然后,只需将弹性和弹跳逻辑写为行为。
答案 1 :(得分:2)
一旦你将层次结构分开,就无法在java中合并它们。
设计问题:如果您知道可以将ElasticBall
和BouncingBall
组合在一起,则应创建两个接口Elastic
和Bouncing
,两者均可扩展接口Ball
,常用方法对两者都有效。
然后可以将常用方法实现设置为公共抽象类,让我们说AbstractBall
。此时,您最终可以详细说明您的三个实现:
ElasticBall extends AbstractBall implements Elastic
BouncingBall extendis AbstractBall implements Bouncing
ElasticBouncingBall extends AbstractBall implements Elastic, Bouncing
通过这种方式,您将能够控制每个方法中的操作,重用常见内容的代码(在抽象类中)。
答案 2 :(得分:1)
您可以使用允许多重继承的接口。为每个球ElasticBall
和BouncingBall
创建界面,并在BouncingElasticBall
中实现这两个界面。