【问题标题】:Java why interface extends interfaceJava为什么接口扩展接口
【发布时间】:2012-11-06 09:22:56
【问题描述】:

我想知道在什么情况下我们从接口扩展接口?因为,例如

interface A{
    public void method1();
}
interface B extends A{
    public void method2();
}
class C implements B{
    @Override public void method1(){}
    @Override public void method2(){}
}

不就相当于

interface A{
    public void method1();
}
interface B{
    public void method2();     
}
class C implements A, B{
    @Override public void method1(){}
    @Override public void method2(){}
}

背后有什么重要原因吗?

【问题讨论】:

  • 第一种情况C类的编码者不需要知道B继承A的细节,他只需要阅读B的文档。
  • @peter 考虑选择“最佳答案”

标签: java inheritance interface extends


【解决方案1】:

重要的原因完全取决于界面应该做什么。

如果你有一个接口 Vehicle 和一个接口 Drivable ,那么所有车辆都是可驱动的。如果没有接口继承,每种不同类型的汽车类都需要

class ChevyVolt implements Vehicle, Drivable
class FordEscort implements Vehicle, Drivable
class ToyotaPrius implements Vehicle, Drivable

等等。

就像我说的那样,所有车辆都是可驾驶的,因此更容易拥有:

class ChevyVolt implements Vehicle
class FordEscort implements Vehicle
class ToyotaPrius implements Vehicle

车辆如下:

interface Vehicle extends Drivable

而且不必考虑。

【讨论】:

  • 如果你给 Vehicle interface extends Drivable interface in coded block,那不是更好吗?
【解决方案2】:

是的,它就像在其他任何地方的继承一样。如果 B 是 A 的一个 特化,那么它应该这样写。第二个表示该类恰好实现了两个接口,它们之间没有任何关系。

从最终结果的角度来看,您可以只使用多个接口来代替处理层次结构(就像您可以避免在类层次结构中使用继承行为一样)。然而,这会使信息更加分散,并且(如果不是更多的话)明显地混淆了软件模型的意图。

【讨论】:

  • A 和 B 是 interfaces 的。那么,当你说BA 是什么意思。 interface 是在设计具体类之后发现的。我觉得扩展接口源于糟糕的设计。如果您理解inherit 的含义,那么继承接口是没有意义的。继承具体类是有意义的,因为它们代表或显示了现实世界对象的性质,而您继承了这种性质,因为SubType 也是这种性质的一部分。顺便说一句,你能给我一个关于扩展接口的 jdk 示例吗?我想分析一下。
  • 具体类对应于“现实世界对象”的实现,而接口代表它们的契约或定义究竟应该“显示”什么。一般来说,如果您有一个具有合同专业化的类层次结构,那么相应的接口层次结构可能会很有意义。我不打算为你研究示例,但我敢打赌 Collections API 已经满是它们了。
  • 所以,当有人说,public interface List extends Collection{} 你的意思是,ListIterable,因为ListCollectionCollectionIterable?我认为这是错误的。从了解系列设计师的甲骨文技术人员那里查看answer。基本上我的观点是,从设计角度扩展 interface 是没有意义的。
  • 该线程涵盖了您正在雄心勃勃地概括的特定实例。底层讨论是关于 Java 的单一实现继承的限制,这是整个对话的基础,也是为什么虽然使用抽象类和方法(如模板方法)的扩展可能是首选,但它们不能通用的原因。刮掉单个层并单独评估扩展 Iterable 更具代表性。我肯定会说界面层次结构不应该很深。
  • 我做到了。我说这是断章取义和笼统的。答案并不是说扩展接口是不好的做法,只是当专业化意味着可以一致实现的特定功能时,它们应该被处理,而不是不必要地将责任转移给实现者。我并不是说应该盲目地采用这种做法,但您是说应该完全避免这种做法,因此您更需要对 Iterable 评论做出回应。
【解决方案3】:

是的,有一个很大的不同。

在您的第一个示例中,您的新接口 B 被定义为从 A 扩展,因此今后,任何实现 B 的类自动实现 A。基本上,您'重新告诉编译器“这就是成为 A 的含义,这就是成为 B 的含义,哦,顺便说一句,所有 B 也是 A 的!”这样你就可以说...

class C implements B {
    ... you implement all of the methods you need...
    ...blah...
    ...blah...
}
A myNewA = new C();

而且效果很好。

但是,在您的 second 示例中,您没有声明 B 来扩展 A,因此上面的代码不起作用。当您尝试将(第二种)C 的实例分配给 A 的引用时,它会抱怨,因为您没有告诉编译器“所有 B 都是真正的 A”。 (即BC之间没有关系)

【讨论】:

    【解决方案4】:

    只有一条评论

    interface A{
        public void method1();
    }
    interface B extends A{
        public void method2();
    }
    class C implements B{
        @Override public void method1(){}
        @Override public void method2(){}
    }
    

    如果你声明A a = new C();

    你不能调用method2();,因为接口A对接口B中的元素一无所知,即使你实现了类C中的方法

    【讨论】:

      【解决方案5】:

      如果你不想在没有实现 A 的情况下实现 B,你可以让 B 扩展 A。

      例子:

      interface LivingThing{
      public void eat();
      }
      
      interface Dog extends LivingThing{
      public void Bark();
      }
      

      不做狗就可以做一个活的东西,但不做一个活的东西就不可能做一只狗。因此,如果它会吠叫它也可以吃东西,但并非总是如此。

      【讨论】:

        【解决方案6】:

        你说的是对的,但这不仅仅是为了完成我们的工作,如果需求是这样的:

        1) 假设有 10 个接口,不是同时设计的。例如Java 7 中的 AutoCloseable 接口。添加了一个新的自动关闭功能,直到 Java 6 才出现。

        2) 如果您设计了一个作为标记接口的接口 C,并且您希望从给定类 B 派生的所有类都被标记,那么最好的解决方案是使用 B extends C 而不是将实现 C无处不在。

        还有很多原因。如果您从更大的类和层次结构来看,您可能会自己得到答案。

        乐于提供帮助 达兰

        【讨论】:

          【解决方案7】:

          有时,您不想允许成为B 而不是A,而是希望允许成为A 而不一定是B。 如果ACar 并且BSportCar,您可能只想使用Car 接口来处理一些流,但有时需要更具体并明确使用SportCar。这样一来,您就不能决定哪一天只实现SportCar。它也迫使您实施Car。这正是OOP中继承的意思。

          此外,假设您想要声明一个实现SportCar 的新类成员。你如何让它也实现Car接口?据我所知,没有办法添加由多个接口组成的类型。

          public SportCar myCar;
          // public SportCar,Car myCar -> invalid
          

          这样你就不能保证myCar 会有一个Car 的方法(比如Drive()),这样就失去了从继承中获得的优势。

          【讨论】:

            【解决方案8】:

            这里的主要区别是,在您的第一个示例中,B 是 A,然后是一些。这意味着接口 B 调用 method1() 和 method2(),而在第二个中,A 和 B 是分开的(接口 B 不得出 method1())并且类 C 实现 A 和 B。在这两个实例中,类 C 将覆盖 method1 () 和方法 2()。我希望这会有所帮助!

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2023-03-22
              • 2015-04-06
              • 2012-10-23
              • 1970-01-01
              • 2011-01-14
              • 2012-12-19
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多