【问题标题】:Why we should use Interface, instead of concrete types?为什么我们应该使用接口,而不是具体类型?
【发布时间】:2013-10-04 08:36:00
【问题描述】:

在 Java 中使用集合时,建议使用接口而不是具体类型。

点赞:List<Object> list = new ArrayList<Object>();

但是,使用ArrayList<Object> list = new ArrayList<Object>(); 也可以完成同样的工作,对吧?

【问题讨论】:

  • 原因是多态性
  • 我在等这个爆炸:D
  • 只是现实生活中的一个例子。我不得不使用动态代理来做一个解决方法(长篇大论),但正如你已经知道的那样,要制作动态代理,你必须使用接口。但是你猜,项目中的所有引用都是具体的类型引用。所以我不得不重构所有使用具体类型及其接口的方法。工作量不大,但教训是,为了面向对象编程,您必须使用接口,因为您永远不知道何时有人/您必须替换具体类型。

标签: java collections arraylist


【解决方案1】:

是的,但是如果您以后改变主意并使用LinkedList,则必须在代码中进行更多更改。

【讨论】:

    【解决方案2】:

    这就是多态性,它是面向对象编程的核心概念。

    它的意思是“具有多种形状的状态”或“具有不同形式的能力”。当应用于 OOP 时,它描述了一种语言通过单一、统一的接口处理各种类型和类的对象的能力。

    List是一个统一接口,它的不同实现类似于ArrayList ,LinkedList.....等

    喜欢阅读:What does it mean to program to a interface?

    【讨论】:

      【解决方案3】:

      当您将列表定义为:

      List myList = new ArrayList();
      

      您只能调用属于 List 类的方法和引用成员。如果定义为:

      ArrayList myList = new ArrayList();
      

      除了从 List 继承的成员之外,您将能够调用 ArrayList 特定方法并使用 ArrayList 特定成员。 然而,当您在第一个示例中调用 List 类的方法时,该方法在 ArrayList 中被覆盖,那么来自 ArrayList 的方法将被调用而不是 List 中的方法。 第一个优点是 List 的实现可以更改(例如更改为LinkedList),而不会影响其余代码。使用ArrayList 很难做到这一点,不仅因为您需要在任何地方将ArrayList 更改为LinkedList,还因为您可能使用了ArrayList 特定方法。

      【讨论】:

        【解决方案4】:

        有一个有用的原则:对于声明的类型,尽可能使用最松散(模糊)的接口(并且ListArrayList '宽松')。

        实际上,这意味着如果您只需要访问在您的列表实例(实际上是一个ArrayList)上声明在List<Object> 中的方法,则将其声明为List<Object>。这意味着您可以稍后改变您对列表的确切类型的想法,您只需要更改实际实例化 ArrayList(或 LinkedList 或您选择的任何内容)的行。

        这对方法签名也有影响:如果您传递的是 ArrayList 而不是 List,然后又改变了主意,认为它是 ArrayList,您必须去编辑很多方法签名.

        如果您想了解更多信息,请阅读Polymorphism

        与里氏替换原则相切相关:

        What is the Liskov Substitution Principle?

        【讨论】:

          【解决方案5】:

          接口或者我应该说基本类用于概括手头的事物和问题。所以当你实现一个接口时,你总是可以得到特定的对象。

          例如: 从Animal interfacesuper class 你总是可以派生 特定的接口或类如Lion,但不能反过来,因为Lion 确实是一种动物但其他几种动物不能衍生自狮子。这就是为什么建议使事情通用并因此使用interfaces。 同样适用于您的情况。您始终可以从List 获得ArrayList 和其他实现。

          【讨论】:

            【解决方案6】:

            假设你有一个具有以下方法的类

            public ArrayList<T> foo (ArrayList<T> someInput) {
            
                //Do some  operations on someInput here...
            
                return someOutput;
            
            }
            

            现在,如果您更改程序使其使用LinkedList 对象而不是ArrayList 对象会发生什么?无论何时调用此方法,您都会收到编译器错误,您必须检查并重构您的代码,以便它接受 LinkedList 对象。

            如果您已对接口进行编程并使用列表代替:

            public List<T> foo (List<T> someInput) {
            
                //Do some operations on someInput here....
            
                return someOutput;
            
            }
            

            如果是这种情况,则无需重构,因为 LinkedListArrayList 类都实现了 List,因此不会出现编译器错误。这使得它非常灵活。只要对象实现 List 接口,方法接收什么和返回什么并不重要。这允许您在不暴露任何底层实现的情况下定义行为。

            【讨论】:

              猜你喜欢
              • 2021-10-25
              相关资源
              最近更新 更多