25

最近我决定看一下 Java,所以我对它和 OO 编程的方法仍然很陌生,所以我想在学习更多之前先搞清楚一些东西,(我想从好的实践开始永远不会很快)。

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

我有不同种类的僵尸,但它们都具有相同的属性(x、y、健康、攻击等),所以我编写了一个接口Zombie,由 WalkingZombie、RunningZombie TeleportingZombie 等实现。这是最好的做法吗?我更喜欢抽象类吗?还是有一个超级班?(我不打算部分实现功能 - 因此我选择接口而不是抽象类

我有一个描述主角(幸存者)的类,由于它很大,我想编写一个具有不同功能的界面,以便我可以轻松查看和分享它的结构。这是好习惯吗?还是只是浪费空间和时间?

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

4

9 回答 9

17

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

另一方面,当您有一些您想要实现的所有子类可能共有的代码时,将使用抽象类。因此,您可能有一个名为 Shape 的抽象类,它有一些通用代码,并且在您的派生类(Circle、Square 等)中,您可能有特定于这些形状的代码(getArea例如)。但是颜色之类的东西可能对所有形状都是通用的,因此您可以getColor在 Shape 抽象类中放置一个方法。

你可以将这两个想法结合起来。您可以拥有实现接口的抽象类,这为您提供了两全其美的优势。

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

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

于 2010-05-19T20:47:56.893 回答
4

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

封装变化: - 在自己的类中定义独特的行为。参考上面的示例,在其单独的类中实现步行、跑步和传送的行为。这样,实现了多态行为。

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

于 2010-05-19T21:44:19.380 回答
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 =一页&q&f=假

因此,您可以将所有行为实现为独立的类,然后通过实现和组合为每个僵尸实现赋予其自己的行为组合。

希望这有意义并有所帮助...

于 2010-05-19T21:02:18.097 回答
1

I have different kinds of zombies, but they all have the same attributes (x, y, health, attack etc) so i wrote an interface Zombie which i implement by WalkingZombie, RunningZombie TeleportingZombie etc. Is this the best thing to do? Am i better of with an abstract class? Or with a super class?

an abstract class will be a super class for your zombies. an interface would also in some sense be a super class (super interface?) for your zombies.

the common properties suggest at least an abstract base class for common properties.

(I am not planning to partially implement functions - therefor my choice for an interface instead of an abstract class)

not sure what you mean by this.

if you had different kinds of monsters (goblins, orcs, etc.) you might find behaviour common to these that would want to belong to different base classes. this would suggest an interface.

i would start with an abstract base class and see what the code tells you as you write it.

I have one class describing the main character (Survivor) and since it is pretty big i wanted to write an interface with the different functions, so that i can easily see and share the structure of it. Is it good practice? Or is it simply a waste of space and time?

your survivor is what is called a player-character (as opposed to a non-player character - someone in a game who will normally not attack your survivor).

most games treat all of these character types as some kind of monster since they will all have many properties in common (health. magic, treasures, weapons, etc.)

so perhaps that's more of an argument for an interface.

see:

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

于 2010-05-19T23:17:34.383 回答
1

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

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

于 2010-05-19T20:52:52.830 回答
1

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

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

如果你真的很喜欢这些东西,你可能还想看看 mixins。这不是 Java 直接支持的东西,但有一些为它构建的库。

于 2010-05-19T20:54:53.120 回答
0

我认为在您的情况下,您的接口和类结构与现实不符。事实上,我相信(如果我错了,请纠正我)每个僵尸都可以行走、奔跑、传送等,具体取决于它所在的位置。

因此,您应该有一个僵尸类或接口,并具有修改僵尸状态的操作。该动作可能是一个接口或一个抽象类,因此您可以将任何动作应用于僵尸而不知道确切的动作做什么(例如action.perform(zobie))。

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

于 2010-05-19T20:47:13.487 回答
0

我的意见是你最好使用名为Creature的抽象类作为所有类型的生物的超类,并将其扩展到所有类型的僵尸的Zombie
而且你还需要一个接口..来定义一个生物可以做的事情..
比如走路、抓爪或尖叫......
你需要一个抽象类的原因是禁用Creature的实例化,你不会想要一个不知道它是什么生物的生物,对吧?

于 2010-05-20T02:10:47.107 回答
0

就您的僵尸示例而言,界面会很好,除非您有希望所有僵尸都执行的通用代码。

假设你有一个Move方法,可以让walkingzombies 走,runningzombies 跑,等等。但是,如果你想让“Move”让任何一种僵尸做一些常见的事情,那么界面将迫使你复制代码,因为你不能放界面中的主体。

于 2010-05-19T20:50:51.693 回答