【问题标题】:How to extend an interface如何扩展接口
【发布时间】:2012-09-01 22:47:10
【问题描述】:

我正在编写接口代码。

我有一个接口 A 和一个实现它的类 B

我被告知我可以通过 C 扩展来覆盖 B 的 功能,但我被要求既不碰 B 也不碰 C,然后在配置文件中将B替换为C作为A的实现类。

我想我需要一个 A 中没有的方法,所以我需要向 A 添加一个我可以在 C。但是我不能碰A

有人可以帮我解决怎么做吗?

谢谢。

编辑示例代码:

A.java

public interface A {
    void X();
    void Y();
}

B.java

public class B implements A {
    public void X() {//something interesting}
    public void Y() {//something not very interesting}
}

现在因为不允许我触摸 AB 我不得不编写另一个类 C 并将其从 B 扩展来做我的事情。

C.java

public class C extends B {
    public void Y() {//overriding B's not very interesting Y and making it interesting}
}

现在我需要 C.java 中的另一个方法 void Z() 来做我的事情,但是因为如果我在 C.java 在使用A's 引用变量时,我将无法调用Z(),所以我必须在A 接口中声明void Z() 才能像那样使用它,但如果我这样做,我将不得不触摸A,我不允许这样做。所以如何解决这个问题是我一直想问的。

所以本质上,我将无法执行以下操作:

A a = new C();
a.Z(); //can't do this

那么我有什么方法可以在不触及 A 或 B 的情况下实现类似的目标?

【问题讨论】:

  • 你的意思是:既不碰A也不碰B
  • 加:为什么你不能有一个不在界面中的方法?这不是 Objective-C!
  • 是的,我知道这在 ObjC 中也是可能的,但在那里更常见。
  • 你不能碰 A、B 或 C,必须用 C 的 A 实现替换 B?这是不可能的,除非您可以更改 C 或将 C 扩展到 D 并将 B 替换为 D 的新实现。您不能在接口 A 之外添加新方法并期望它被 A 接口的默认使用者使用。
  • 好的,但你到底是什么意思?

标签: java design-patterns inheritance interface


【解决方案1】:

我想我明白你想要什么。您有以下内容:

public interface A {
  // can't touch this
}

public class B implements A {
  // can't touch this
}

public class C extends B {
  // you want to add your own method
  void someNewMethod();
}

// And you wish to do this:
A foo = new C();
foo.someNewMethod();

如果这是你想要的,那恐怕做不到。任何使用A 的人都只知道A 中定义的方法;他们不会知道你在课堂C 中定义了someNewMethod()。您需要被允许更改A

请注意,在极端情况下,您可以检查A 实例的类类型:

A foo;
// ...

if (foo instanceof C) {
  ((C) foo).someNewMethod();
}

但那真的很丑并且违反了许多面向对象编程的基本规则。

【讨论】:

    【解决方案2】:

    我不知道你是否被允许这样做,但你可以扩展接口和类,你可以这样做:

    公共接口 A2 扩展 A { 公共无效 mySuperVeryInterestingNewMethod(); }

    【讨论】:

    • 这可以做到,但问题是正在处理的应用程序有太多A 的实例,以至于无法想象用A2 替换所有A 的实例。没有任何其他选择,所以我不得不在接口A 本身中声明该方法。感谢您的回复:)。
    • 如果您按 ctrl+单击/右键单击选项,Eclipse 有一个“重构”选项。那不是那么难! @跳过
    【解决方案3】:

    那么,按照你刚才写的,你不能碰A、B、C……所以,用D扩展C?

    然后你可以添加你需要/想要的任何方法。

    【讨论】:

    • 我不能只碰AB。我创建了C,因为我必须重写B 中实现的一些方法。问题是我对接口进行编码,所以我使用A 类型的引用变量,但A 的实现类可能是BCD but I've got to have that new method that I want to use declared in A`,供A's 使用参考变量调用该方法。
    【解决方案4】:

    您的问题根本不清楚。这是你的意思还是你想要的?

    public interface InterfaceA
    {
    
    }
    
    public class ClassB implements InterfaceA
    {
    
    }
    
    public class ClassC extends ClassB
    {
    
    }
    
    public class ClassD extends ClassC
    {
    
    }
    
    public class Main
    {
        protected InterfaceA A;
    
        public Main()
        {
            //A = new ClassB();
            A = new ClassD();
        }
    
    
        public static void main(String[]args)
        {
        }
    }
    

    【讨论】:

    • 我不能只碰AB。我创建了C,因为我必须重写B 中实现的一些方法。问题是我对接口进行编码,所以我使用A 类型的引用变量,但A 的实现类可能是BCD but I've got to have that new method that I want to use declared in A`,供A's 使用参考变量调用该方法。
    【解决方案5】:

    如果该方法是支持的,则无需将其添加到接口来​​实现它。如果它在其他地方使用,则 B 实现另一个接口 D。

    【讨论】:

    • 这里的整个问题是编码到接口A。在客户端,我使用 A 的引用变量来调用方法。
    • 我想我跟着。你有一个类型为 A 的变量。你知道它是一个 B,你需要调用一个不在 A 接口中的方法。您需要直接引用 B 而不是引用泛化 A 或尝试尝试转换为 B 并处理错误转换
    【解决方案6】:

    这可能会解决您的问题:

    package test;
    
    public interface A {
    
        void X();
        void Y();
    
    }
    
    
    package test;
    
    public class B implements A{
    
        @Override
        public void X() {
    
            System.out.println("Something X");
    
        }
    
        @Override
        public void Y() {
    
            System.out.println("Something Y");
        }
    
    
    
    }
    
    package test;
    
    public class C extends B implements A{
    
        public static void main(String[] args) {
    
            A a=new C();
            a.X();
            a.Y();
    
        }
    
    }
    

    根据您的要求

    1-你已经创建了一个接口A。

    2-创建了一个实现 A 的类 B。

    3-创建了一个扩展 B 并实现 A 的类 C。

    4- A a=new C() 将创建 A 类型的引用变量,但在运行时它将保存 C 的对象。

    由于您不能触摸 B 和 C,因此签名是相同的,并且您使用 C 的对象从 B 调用 X() 和 Y(),因为它扩展了 B。

    因此,您已将 B 替换为 C,而没有在 C 中实现 X 和 Y 并对 B 进行更改。

    输出:

    Something X
    Something Y
    

    希望这能回答你的问题。

    【讨论】:

      猜你喜欢
      • 2022-01-14
      • 2018-08-22
      • 1970-01-01
      • 1970-01-01
      • 2015-08-09
      • 2020-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多