在两个类之间共享代码

时间:2011-03-06 03:24:32

标签: java inheritance

我正在用Java开发服务器应用程序。服务器需要两种类型的服务器类。这些类有一些共同的方法,这些方法中的代码完全相同。所以我创建了一个包含所有共享代码的抽象超类,并且这两个类都继承了它。但是,有些部分代码需要由子类进行预处理。我的意思是超类“依赖”子类方法。

这是我的意思的纯化例子:

public abstract class AbstractServer
{
    public void loadConfig(String configPath)
    {
        //Load the configuration file.

        //This code is exactly the same for subclasses.
    }

    public void startRMI(int port)
    {
        //Create an empty RMI registry.
        //This part also need to be identical.

        //Here' where the superclass "rely" on subclasses.
        fillRegistry(); //Call the method overwritten by subclasses.
    }

    /**
    Bind remote objects in the RMI registry
    */
    protected abstract void fillRegistry(); //This method will be overriten by subclasses.
}

我觉得这样做真是太糟糕了,但我找不到另一种更清洁的方法。

所以,我想要的是如何让它变得更好。

谢谢,抱歉我的英语不好。

6 个答案:

答案 0 :(得分:0)

在编辑后看起来对我说话(假设你遗漏了Exception投掷部分以便于阅读):)

这三种方法都需要在现实案例中引发异常。

答案 1 :(得分:0)

超类由子类继承。你可以在超类中编写你想要共同的方法并保持不变。对于您希望它被子类覆盖的代码的其他部分,在超类中定义其他方法集。在子类中也写入方法。当你从子类调用方法时你可以调用超类方法的

总之,你必须在子类中编写方法来重写超类的方法。

答案 2 :(得分:0)

我还要确保你的超类实际上是抽象的。在这个片段中它不是。总的来说,看起来不错。

还要考虑在超类中声明任何扩展它的类都需要的实例变量。

答案 3 :(得分:0)

首先,在抽象(基类)类中要求子类的实现没有任何问题。这只是一些不应该被滥用的东西,IMO。但是,如果我不得不避免它,我会将ServerClass 抽象,并定义它的每个方法。相反,我会创建RegistryFactory类并将它们传递给ServerClass:

class ServerClass {
   public void startRMI(int port, RegistryFactory rf) {
      // ...
      rf.fillRegistry(this);
   }
}


interface RegistryFactory {
   /**
    * Implement this method
    */
   public void fillRegistry(ServerClass server);
}

public class RMIRegistryFactory implements RegistryFactory {
   public void fillRegistry(ServerClass server) { /* ... */ }
}

或类似的东西。

答案 4 :(得分:0)

你的方法很好。坚持好友。

我觉得你理解它的'哲学需要'。只要基类是抽象的,基类“依赖”子类就可以了。它知道此时必须注册一些东西,但它没有关于究竟要注册什么的最微弱的线索。因此,高级进程在基类中编码,其中“孔”可以由派生类插入。高级过程和“漏洞”本身的位置是有价值的,这证明了基类的实现是正确的。派生类只遵循“按差异编码”的基本OO原则并插入“漏洞”。

答案 5 :(得分:0)

您的方法很好,但是需要对其进行简单的改进以使其完美-使startRMI()方法final

public final void startRMI(int port) {
    fillRegistry();
}

这样,您可以防止某人重写它(可能是因为不知道startRMI()中的所有内容都应被重用,并且仅fillRegistry()必须自定义)。

您的解决方案通常与template method design pattern相匹配:

  

模板方法是超类中的方法,通常是抽象的   父类,并根据   高级步骤数。这些步骤本身是由   与模板方法在同一类中的其他辅助方法。

     

在这种情况下,辅助方法可以是抽象方法   需要子类来提供具体的实现或挂钩   方法,在超类中具有空的主体。 子类可以   (但不是必须)通过覆盖   挂钩方法。模板方法的目的是定义   操作的整体结构,同时允许子类   完善或重新定义某些步骤。 (维基百科)

鉴于上述情况,方法startRMI()是一种模板方法,它通过使用许多高级步骤来定义操作的框架(在您的情况下,这只是一个步骤,但这没有什么区别)。您示例中的方法fillRegistry()是一个高级步骤-在超类中被定义为抽象方法,并且在超类中具有具体的实现。

另一方面,如果您要在子类中覆盖方法startRMI(),将不再可行。这就是为什么您应该将其设置为final以避免混淆-这样,创建子类的人将知道他必须实现fillRegistry()(因为它是抽象的),但不应更改startRMI的实现(因为它是最终的)。

因为这是一种常用的设计模式,所以我完全不担心这种解决方案是否可行,很多人正在这样做,并且知道设计模式的每个人都会意识到这一点,我认为这很自然甚至对于不了解设计模式的开发人员。