JavaRush /Java 博客 /Random-ZH /Java 中的接口

Java 中的接口

已在 Random-ZH 群组中发布
你好!今天我们来谈谈Java中的一个重要概念——接口。这个词你可能很熟悉。例如,大多数计算机程序和游戏都有界面。从广义上讲,界面是一种连接交互两方的“遥控器”。日常生活中的接口的一个简单示例是电视遥控器。它连接两个物体,一个人和一台电视,并执行不同的任务:调高或调低音量、改变频道、打开或关闭电视。一侧(人)需要访问界面(按下遥控器按钮),另一侧才能执行操作。例如,让电视切换到下一个频道。在这种情况下,用户不需要知道电视的设备以及其内部如何实现改变频道的过程。为什么Java中需要接口 - 1用户可以访问的只是界面。主要任务是获得期望的结果。这与编程和 Java 有什么关系?直接:) 创建接口与创建常规类非常相似,只是class我们指定的单词不是interface。让我们看一下最简单的 Java 接口,并弄清楚它是如何工作的以及它的用途:
public interface Swimmable  {

     public void swim();
}
我们创建了一个可以游泳的Swimmable界面。这就像我们的遥控器,有一个“按钮”:方法 是“游泳”。我们该如何使用这个“遥控器”呢?为此,该方法,即 我们遥控器上的按钮需要实现。要使用接口,它的方法必须由我们程序的某些类实现。让我们设计一个类,其对象符合“可以游泳”的描述。例如,鸭子类就适合: swim()Duck
public class Duck implements Swimmable {

    public void swim() {
        System.out.println("Duck, swim!");
    }

    public static void main(String[] args) {

        Duck duck = new Duck();
        duck.swim();
    }
}
我们在这里看到什么?使用关键字将类Duck与接口关联起来。如果你还记得的话,我们在继承中使用了类似的机制来连接两个类,只是有“ extends ”这个词。为了清楚起见, “ ”可以按字面意思翻译:“公共类实现接口。” 这意味着与接口关联的类必须实现其所有方法。请注意:在我们的类中,就像在接口中一样,有一个方法,并且里面有某种逻辑。这是强制性要求。如果我们只写了“ ”,并没有在类中创建方法,编译器会给我们一个错误: Duck is not abstract and does not override abstract method Swim() in Swimmable 为什么会发生这种情况呢?如果我们用电视的例子来解释这个错误,就会发现我们给一个人一个带有“更改频道”按钮的遥控器,而电视却不知道如何更改频道。此时,无论按多少次按钮,都不会起作用。遥控器本身并不改变频道:它只是向电视发出信号,电视内部执行了一个复杂的改变频道的过程。我们的鸭子也是如此:它必须能够游泳,以便可以使用接口访问它。如果她不知道如何做到这一点,界面将无法连接两个方面——人和程序。人无法使用方法使程序内的对象浮动。现在您已经更清楚地了解了接口的用途。接口描述了实现该接口的类必须具有的行为。“行为”是方法的集合。如果我们想创建多个信使,最简单的方法是创建一个接口。任何使者应该能够做什么?以简化的形式接收和发送消息。 Swimmableimplementspublic class Duck implements SwimmableDuckSwimmableDuckSwimmableswim()public class Duck implements Swimmableswim()DuckSwimmableSwimmableswim()DuckMessenger
public interface Messenger{

     public void sendMessage();

     public void getMessage();
}
现在我们可以通过实现这个接口来简单地创建我们的信使类。编译器本身会“强迫”我们在类中实现它们。电报:
public class Telegram implements Messenger {

    public void sendMessage() {

        System.out.println("Sending a message to Telegram!");
    }

     public void getMessage() {
         System.out.println("Reading the message in Telegram!");
     }
}
微信:
public class WhatsApp implements Messenger {

    public void sendMessage() {

        System.out.println("Sending a WhatsApp message!");
    }

     public void getMessage() {
         System.out.println("Reading a WhatsApp message!");
     }
}
维伯:
public class Viber implements Messenger {

    public void sendMessage() {

        System.out.println("Sending a message to Viber!");
    }

     public void getMessage() {
         System.out.println("Reading a message in Viber!");
     }
}
这有什么好处?其中最重要的是松耦合。想象一下,我们正在设计一个程序,我们将在其中收集客户数据。该类Client必须有一个字段指示客户端使用哪个信使。如果没有接口,它看起来会很奇怪:
public class Client {

    private WhatsApp whatsApp;
    private Telegram telegram;
    private Viber viber;
}
我们创建了三个字段,但一个客户很容易只有一个信使。我们只是不知道是哪一个。为了不与客户失去沟通,你必须将所有可能的选项“推”到课堂上。事实证明,其中一两个总是存在null,并且程序运行根本不需要它们。相反,最好使用我们的界面:
public class Client {

    private Messenger messenger;
}
这是“松耦合”的一个例子!我们没有在类中指定特定的信使类Client,而是简单地提到客户端有一个信使。哪一个将在计划过程中确定。但为什么我们需要接口呢?为什么要将它们添加到语言中?这个问题问得好,也正确!使用普通继承也可以达到相同的结果,对吗?该类Messenger是父类, 、和Viber是继承人。确实,这样做是可能的。但有一个问题。正如您所知,Java 中不存在多重继承。但接口有多种实现。一个类可以实现任意多个接口。想象一下,我们有一个类,它有一个字段- 一个安装在智能手机上的应用程序。 TelegramWhatsAppSmartphoneApplication
public class Smartphone {

    private Application application;
}
当然,应用程序和信使很相似,但它们仍然是不同的东西。Messenger 可以是移动端和桌面端,而 Application 是移动应用程序。因此,如果我们使用继承,我们将无法Telegram向类添加对象Smartphone。毕竟,一个类Telegram不能继承ApplicationMessenger!我们已经成功地从 继承它Messenger,并以这种形式将其添加到类中Client。但是一个类Telegram可以轻松实现这两个接口!因此,在类中Client我们可以将对象实现TelegramMessenger,在类中Smartphone实现为Application。其操作方法如下:
public class Telegram implements Application, Messenger {

    //...methods
}

public class Client {

    private Messenger messenger;

    public Client() {
        this.messenger = new Telegram();
    }
}


public class Smartphone {

    private Application application;

    public Smartphone() {
        this.application = new Telegram();
    }
}
Telegram现在我们可以随意 使用这个类了。他将在某个地方扮演...的角色Application,在某个地方扮演...的角色Messenger。您可能已经注意到接口中的方法总是“空”,也就是说,它们没有实现。原因很简单:接口描述行为,而不是实现它。“实现该接口的类的所有对象都Swimmable必须能够浮动”:这就是接口告诉我们的全部内容。Fish鱼、鸭或马到底如何游泳是类、Duck和的问题Horse,而不是接口的问题。就像改变频道是电视的任务一样。遥控器只是给您一个按钮即可执行此操作。然而,Java8 有一个有趣的补充——默认方法。例如,您的接口有 10 个方法。其中 9 个在不同类中实现不同,但其中 1 个在所有类中实现相同。以前,在Java8发布之前,接口内的方法根本没有实现:编译器立即抛出错误。现在你可以这样做:
public interface Swimmable {

   public default void swim() {
       System.out.println("Swim!");
   }

   public void eat();

   public void run();
}
使用关键字default,我们在接口中创建了一个具有默认实现的方法。我们需要在所有要实现 的类中实现另外两个方法eat()和。无需使用该方法执行此操作:所有类中的实现都是相同的。顺便说一句,您在过去的任务中不止一次遇到过接口,尽管您自己没有注意到:)这是一个明显的例子: 您使用接口并且!更准确地说,是通过它们的实现 - 、和其他。同一张图显示了一个类同时实现多个接口的示例。例如,它实现了接口and (双面队列)。您还熟悉该接口,或者更确切地说,熟悉它的实现。顺便说一句,在这张图中你可以看到一个特性:接口可以相互继承。该接口继承自,并且继承自queue 。如果您想显示接口之间的连接,但一个接口是另一个接口的扩展版本,则这是必要的。让我们看一个带有接口的示例- 队列。我们还没有浏览过这些系列,但它们非常简单,排列得就像商店里的常规队伍一样。您只能将元素添加到队列的末尾,并且只能从开头将它们删除。在某个阶段,开发人员需要队列的扩展版本,以便可以从两侧添加和接收元素。这就是创建接口的方式——双向队列。它包含常规队列的所有方法,因为它是双向队列的“父级”,但添加了新方法。 run()Swimmableswim()为什么我们需要 Java 中的接口 - 2ListSetArrayListLinkedListHashSetLinkedListListDequeMapHashMapSortedMapMapDequeQueueQueueQueueDeque
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION