【问题标题】:Would this be the correct place to use the java keyword "interface"?这是使用 java 关键字“interface”的正确位置吗?
【发布时间】:2009-04-09 22:13:36
【问题描述】:

我对 Java 比较陌生。在阅读了一些有关寻路的信息后,我阅读了有关使用空类作为“interface”的信息,用于未知对象类型。

我正在开发一个基于医院主题的 Java 游戏。到目前为止,用户可以建立一个接待处和一个全科医生的办公室。它们是两种不同类型的对象,一种是Building,一种是ReceptionDesk。 (在我的班级结构中。)

我的班级结构是这样的:

GridObject-->Building
GridObject-->Item-->usableItem-->ReceptionDesk.

当可用物品可以旋转而建筑物不能旋转时,问题就出现了。鼠标单击事件在网格上,因此调用相同的方法。全科医生的办公室是Building,接待处是ReceptionDesk。只有ReceptionDesk 有方法rotate。右键单击网格时,如果在构建模式下,我必须使用这个“if”语句:

if (currentBuilding.getClass.equals(ReceptionDesk.getClass)

然后我必须创建一个新的ReceptionDesk,使用rotate 方法,然后把那个 前台回currentBuilding GridObject

我不确定我是否很好地解释了这个问题。对不起。我对 Java 还是很陌生。我将尝试回答任何问题,如果需要,我可以发布更多代码片段。我不知道可能有办法解决不知道对象类的问题,但是我也可能以错误的方式处理它。

直到我看到这个网站上的回复如此快速和有帮助时,我才打算研究这个! :)

提前致谢。

相对

【问题讨论】:

    标签: java interface keyword


    【解决方案1】:

    你不想在对你的情况做某事之前检查一个对象的类。您应该使用polymorphism。你想让接口定义一些方法。每个类都实现这些方法。通过接口引用对象,并让这些对象的各个实现将它们的值返回给调用者。

    如果您再描述一些您认为需要的物品,这里的人们会对您应该如何布置它们有意见。但是根据您提供的内容,您可能需要一个定义一些通用方法的“Building”接口。您可能还需要一个“UsableItem”接口或更通用的东西。医院可以是一个实现构建的类。 ReceptionDesk 可以实现 UsableItem。建筑内部可以有一个 UsableItem 网格。

    如果 rotate() 是所有实际工作的家具的通用方法,您可以考虑创建一个 AbstractUsableItem 类,该类是实现 UsableItem 的抽象类并提供 rotate() 方法。如果每个实现类中的rotate 不同,则接口中会有该方法,但是每个类(如ReceptionDesk)都会使用rotate() 方法做自己的事情。您的代码会执行以下操作:

    UsableItem desk = new ReceptionDesk();
    desk.rotate()
    

    在您的示例中,如果您在屏幕上单击鼠标旋转了其下方的对象,并且您确实需要在执行类似操作之前检查对象是否可以旋转,您会这样做

    if (clickedObject instanceOf UsableItem) {
      ((UsableItem) clickedObject).rotate();
    }
    

    其中 UsableItem 是接口或抽象类。有些人觉得所有的设计都应该通过接口契约来完成,并为每种类型的类建议一个接口,但我不知道你是否必须走那么远。

    【讨论】:

    • 感谢您提供有用的答案和信息。在我完全理解它之前,我将不得不再阅读它,尽管从你链接到我的例子来看,这看起来像是我应该在这里做事的正确方式。
    • 我已进一步阅读此内容,阅读您提供的链接和该网站上的链接。好资源。这无疑是我所追求的答案,尽管它确实假设我理解抽象和接口是什么,但我没有,但我想这是一个公平的假设。
    【解决方案2】:

    您可能会考虑朝着完全不同的方向前进,让对象自己决定采取何种行动。例如,GridObject 接口可能会为 handleRightClick()、handleLeftClick() 等指定函数声明。在这种情况下,您要说的是“任何自称为 GridObject 的类都需要指定当它们被右键单击时会发生什么”。

    因此,在 Building 类中,您可以实现 handleRightClick 以不执行任何操作(或返回错误)。在 ReceptionDesk 类中,您将实现 handleRightClick 来旋转桌子。

    您的代码 sn-p 将变为:

    currentBuilding.handleRightClick(... any necessary parameters ...);
    

    【讨论】:

    • 这看起来像是我一直在寻找的东西!卓见!我相信约翰的回答非常好,但可能有点超出我的想象。我必须在 GridObject 类中使用相同的方法,并将其设置为空,同时让其他类中的同名方法执行操作。
    【解决方案3】:

    你的担心是正确的。面向对象设计的一个好的经验法则是,每当您使用 if(x instanceof Y)if(x.getClass().equals(Y.class)) 这样的结构时,您应该开始考虑向上或向下移动方法,或提取新方法。

    Elliot 和 John 都提出了很好的想法,说明了你可以走的非常不同的方向,但他们都认为你绝对应该朝着某个方向前进。面向对象的设计通过使不同类型行为的分支更加隐含来帮助您的代码变得更加清晰。检查您正在查看的对象类型并据此确定要执行的操作可能会破坏使用面向对象设计的目的。

    我还应该警告您,接口并不完全是一个空类。具有抽象方法和接口的空抽象类之间存在一些显着差异。与其将接口视为空类,不如将接口视为契约。通过实现接口,您的类承诺提供接口中列出的每个方法。

    【讨论】:

    • 谢谢。我确实打算为 if 语句的内部创建方法调用,尽管我不确定“向上或向下移动方法”是什么意思。你能为我解释一下吗?如果我诚实的话,我不能说我理解他们所说的所有内容。我将不得不阅读这方面的内容。
    • 我的意思是将方法移动到超类(向上移动)或子类(向下移动)。对不起,奇怪的行话。我最近读了太多关于重构的书 :)
    • 我一直在考虑这个问题(最终整理出来)。我明白你关于击败使用面向对象设计的观点的说法,但我认为我仍然可以证明这一点,因为一些方法和变量仍然在超类中。我正要(不确定它是否有名字),将类从作为超类的普通类更改为抽象类
    • 如果您想要正式,您正在执行“下推方法”重构(Fowler,“重构”,第 328 页)。如果您使用的是 Eclipse,我相信甚至有一个向导可以为您完成。
    • 太棒了。知道正确的名字我觉得很聪明。我写东西向人们解释东西,它读起来像胡言乱语,但我理解它:)。我看到了用于折射的向导,但我认为我宁愿用手去做,直到我完全理解使用如此强大的向导工具的含义:) 是否有任何文档?我问不是因为我懒惰,而是我想把它记录在这里,作为我的编码天才剪贴簿,你的名字很值得:p
    猜你喜欢
    • 1970-01-01
    • 2011-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-12
    • 2014-02-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多