我正在制作一个游戏。我有一个实体类,它是一对 x,y 坐标以及宽度和高度。
我想将此实体类子类化为几个新类,以添加功能组的组合。我想添加几个“组”功能:
Moveable {
public float getVelocityX();
public void setVelocityX(float velocityX);
public float getVelocityY();
public void setVelocityY(float velocityY);
public void moveRelative(float dx, float dy);
public void setPosX(float posX);
}
和
Rotatable {
public void setAngularVelocity(float degreesPerSecond);
public void setAbsoluteAngle(float angle);
}
和
Resizable {
void setAbsoluteSize(int width, int height);
void setRelativeSize(int widthGrowFactor, int heightGrowFactor);
public void setWidth(float width);
public void setHeight(float height);
}
...以及更多(可更新、可绘制、可碰撞)。
某些实体可以旋转/绘制,但不能移动/碰撞/更新/调整大小:“静态”不可触摸的事物,例如背景动画(云、太阳、星星)。
某些实体可以移动/旋转/绘制/更新/碰撞/调整大小:玩家角色和怪物。
某些实体只能绘制:游戏的 HUD。
某些实体可以移动/绘制/更新/碰撞,但不能旋转/调整大小:例如枪声。
如您所见,我需要组合上述功能,并且可以通过一些多重继承轻松解决。
为什么不使用您要求的接口(interface)来实现呢?因为这会让我为所有方法复制/粘贴大量代码,并且创建新类型的实体类将永远引入复制/粘贴。
您可能会问,为什么我不创建一个可以完成所有操作的子类,然后重写不应该与空方法一起使用的方法,或者在无效方法中抛出 UnsupportedOperationException?尽管每个方法中只有一行,但这仍然是复制/粘贴。只能 move()
的实体最终可能会出现 50 个带有“throw new UnsupportedOperationException();”的方法。这是 Not Acceptable 。
如果您建议适配器模式,我希望您能发布一个示例,说明适配器模式如何执行此类操作(我已经对此进行了辩论)。
如果您建议组合,请解释我将如何访问 protected 字段。
谢谢!
最佳答案
正如罗曼在评论中所说:
Java 确实允许接口(interface)的多重继承
。如果您所需要的只是继承 is-a 关系和一组有保证的方法来与对象进行通信,那么这非常有效。
只能继承一个类
(无论是否抽象)(以及需要的许多接口(interface))。这是为了避免“菱形继承(钻石问题)”的并发症——网络搜索该短语以了解更多信息。如果您确实需要重用多个来源的逻辑,通常的解决方法是在实用程序类中定义其他共享行为,并将您的类委托(delegate)给该实用程序类的实例。是的,这是一个 has-a 关系,而不是 is-a 关系,但由于 is-a 可以抽象为一个接口(interface),因此您可以获得所需的组合行为的最终外观。 (与菱形继承(钻石问题)不同,这迫使您明确决定要调用哪个实现。)
关于java - Java 中可接受的避免多重继承缺失的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21068902/