使用Java [接口/抽象类]

时间:2010-05-19 20:42:13

标签: java interface abstract-class superclass

最近我决定看看Java,所以我还是很新的,也是OO编程的方法,所以我想在学习更多东西之前先做一些事情,(我想它永远不会很快开始有良好做法)。

我现在正在编写一个2D游戏,但我认为我的问题适用于任何非平凡的项目。为了简单起见,我将从游戏中提供示例。

我有不同种类的僵尸,但它们都具有相同的属性(x,y,健康,攻击等)所以我写了一个界面 Zombie,我通过WalkingZombie,RunningZombie TeleportingZombie等实现。这是最好的事吗?我最好使用抽象类?还是使用超类? (我不打算部分实现功能 - 因此我选择接口而不是抽象类

我有一个类描述主角(Survivor),因为它非常大,我想编写一个具有不同功能的接口,这样我就可以轻松地看到并分享它的结构。这是好习惯吗?或者只是浪费空间和时间?

我希望这个问题不会被评为主观,因为我认为有经验的程序员不会对这类话题产生不同意见,因为接口/超类/抽象类的使用遵循逻辑规则,因此不仅仅是个人选择

9 个答案:

答案 0 :(得分:16)

您可以将界面视为“合同”。您正在定义一组实现此接口的类必须实现的方法。

另一方面,如果您有一些代码可能对您要实现的所有子类都是通用的,则使用抽象类。所以你可能有一个名为Shape的抽象类,它有一些公共代码,在派生类(Circle,Square等)中你可以得到特定于那些形状的代码(getArea就是一个例子) 。但是像颜色这样的东西可能对所有形状都很常见,所以你可以在Shape抽象类中放置一个getColor方法。

你可以把这两个想法结合起来。您可以使用实现接口的抽象类,这样可以为您提供两全其美的优势。

这些概念在OO中反复使用,因此理解它们非常重要。你似乎很顺利:)。

因此,如果你的僵尸类有一些适用于所有类型僵尸的常见行为,那么它听起来像是一个抽象类的好候选者。如果你的游戏中有其他角色(也许是GameCharacter或者其他:),你也可以考虑创建一个界面(可能是一个UndeadMice界面)。然后,您的Zombie抽象类和UndeadMouse抽象类将实现GameCharacter接口。

答案 1 :(得分:4)

如果有疑问,我选择遵循GOF范式。

封装变化的内容: - 在自己的类中定义唯一行为。要参考上面的例子,在其单独的类中实现步行,跑步和传送的行为。这样就实现了多态行为。

相反,**聚合常见的东西** - 使用抽象类来定义多态关联中的常见行为。我在设计对象之间的关系时使用这些原则。

答案 2 :(得分:3)

是的,我认为你正在通过抽象类的接口走向正确的轨道。

您可能想要制作的任何具体僵尸都可以拥有您想要实现的步行,跑步或传送功能的任意组合。

我认为现代编程理论尽可能地阻止继承,因为它从长远来看会抑制可重用性和灵活性。相反,使用接口和组合来实现灵活性而无需“紧耦合”。

在没有继承的情况下重用代码的一种方法,您可以应用'优先构成而不是继承'范例。

我觉得Josh Bloch的'Effective Java'(第2版)可以被视为“当前思考”...

http://books.google.com/books?id=ZZOiqZQIbRMC&pg=RA1-PA71&lpg=RA1-PA71&dq=%22Bloch%22+%22Effective+java:+programming+language+guide%22+&hl=de&sig=RxlDlRBWUvNAzsAFzqOcftrYI5E#v=onepage&q&f=false

因此,您可以将所有行为实现为独立类,然后通过实现和实现方式为每个僵尸实现提供自己的行为组合。组合物..

希望这是有道理的&帮助...

答案 3 :(得分:1)

我会把Zombie写成一个抽象类来避免重新定义字段x,y,health等...

对于Survivor类,我只是声明公开要在外部使用的函数。我在类的顶部声明了公共函数。当只有一个实现它的类时,声明一个接口会无用地添加一个文件来维护。避免它。

答案 4 :(得分:1)

没有人同意在超级/抽象类上使用接口;)

使用接口和超级/抽象类的主要原因是启用多态。例如,在你的情况下,你有东西在屏幕上移动(播放器和僵尸等)。为什么不使用相同的方法让它们全部在屏幕上移动?也许从一个名为“Movable”的对象或类似的东西继承将要在屏幕上移动的所有内容。

如果你真的喜欢这些东西,你可能也想看看mixins。这不是Java直接支持的东西,而是为它构建了库。

答案 5 :(得分:1)

  

我有不同种类的僵尸,但它们都具有相同的属性(x,y,健康,   攻击等)所以我写了一个界面Zombie,我通过WalkingZombie实现,   RunningZombie TeleportingZombie等。这是最好的事情吗?我最好还是一个   抽象类?还是有超级班?

抽象类将是僵尸的超级类。在某种意义上,界面也会是你的僵尸的超类(超级界面?)。

公共属性至少建议公共属性的抽象基类。

  

(我不打算部分实现功能 - 因此我选择了一个接口   而不是抽象类)

不确定你的意思。

如果您有不同种类的怪物(地精,兽人等),您可能会发现这些怪物会想要属于不同的基类。这会建议一个界面。

我将从一个抽象基类开始,看看代码在编写时告诉你的内容。

  

我有一个类描述主角(幸存者),因为它非常大我   想要编写一个具有不同功能的界面,这样我就可以轻松看到和   分享它的结构。这是好习惯吗?或者它只是浪费空间和   时间?

你的幸存者是所谓的玩家角色(而不是非玩家角色 - 游戏中通常不会攻击你的幸存者的人)。

大多数游戏都将所有这些角色类型视为某种怪物,因为它们都有许多共同属性(健康。魔法,宝物,武器等)。

所以也许这更像是一个接口的参数。

请参阅:

Using inheritance and polymorphism to solve a common game problem Class diagram examples for RPG (Role Playing Game) designing class hierarchy for typical characters in role playing game

答案 6 :(得分:0)

我不认为在你的情况下你的界面和类结构与现实很好地吻合。事实上,我相信(如果我错了,请纠正我),每个僵尸都可以走路,跑步,传送等,具体取决于它的位置。

因此,你应该拥有一个僵尸类或界面,并拥有修改僵尸状态的动作。该操作可能是一个接口或一个抽象类,因此您可以在不知道具体操作的情况下将任何操作应用于僵尸(例如action.perform(zobie))。

如果您有不同种类的僵尸,例如三足僵尸和单臂僵尸,您可能想要实现处理僵尸内容的不同类,例如显示自己或验证状态变化(例如特殊类型僵尸可能不接受传送)。

答案 7 :(得分:0)

就你的Zombie示例来说,界面会很好,除非你有共同的代码,你想要所有的僵尸做。

假设你有一个Move方法,让步行僵尸走路,跑步僵尸跑等等。但是,如果你想要“移动”让任何一种僵尸做一些常见的事情,那么界面会迫使你重复代码,因为你不能将一个正文放在一个接口中。

答案 8 :(得分:0)

我的观点是你最好使用名为 Creature 的抽象类作为所有类型的生物的超级类,并将其扩展到所有类型僵尸的 Zombie
而且你还需要一个界面..来定义一个生物可以做的事情。
喜欢也许,走路,或抓爪,或尖叫...... 你需要一个抽象类的原因是禁用 Creature 的实例化,你不想让一个生物不知道它是什么生物,对吗?