RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 616119
Accepted
user194625
user194625
Asked:2020-01-18 11:53:13 +0000 UTC2020-01-18 11:53:13 +0000 UTC 2020-01-18 11:53:13 +0000 UTC

为什么界面让生活更轻松?

  • 772

之前从未为“简化生活”编写过自己的界面。为什么?他们有什么有趣的地方?

在评论中,他们要求我将我的知识和工作领域添加到问题中。我编写 android 应用程序和...一切。我对接口一无所知,只知道你可以从接口继承一个类并覆盖方法。但为什么?接口的意义?

感谢您的精彩回答!

java
  • 4 4 个回答
  • 10 Views

4 个回答

  • Voted
  1. Regent
    2020-01-18T14:20:41Z2020-01-18T14:20:41Z

    接口提供了所有实现该接口的类都必须遵循的契约,并且是一种抽象,显示了对象可以做什么,但它如何做并不重要。

    实际上,这会导致以下情况:

    使用接口时,可以用实现相同接口的另一个类替换实现接口的一个类,而无需重写整个代码。例如,如果方法被传递Map:

    public void handle(Map map) { ... }
    

    TreeMap那么如果您想使用instead of ,则不必更改方法描述HashMap。
    同样,如果一个方法返回Map: 它可以开始返回TreeMap而不是HashMap,并且不会有圣经悲剧,因为处理此方法返回值的代码处理Map.
    这增加了代码的灵活性:更容易从一个数据源切换到另一个数据源,从一种实现切换到另一种实现。
    它对于测试也很有用,因为它允许您使用Mock 对象而不是真实对象。


    如果您需要以相同的方式处理元素集合(例如,ArrayList并由y方法Set返回),那么这样描述该方法就足够了:keySet()HashMap

    public <T> void handle(Collection<T> elements) { ... }
    

    这里使用泛型是为了更加真实。在不使用接口的情况下,我不得不创建两种方法:

    public <T> void handle(ArrayList<T> elements) { ... }
    
    public <T> void handle(Set<T> elements) { ... }
    

    然后复制代码,或者,例如,在第二个方法 createArrayList中,将所有元素添加到其中Set并调用第一个方法。


    此外,接口的使用允许您将实现相同接口的不同对象组合到一个列表中,并以相同的方式处理它们:

    public interface Animal
    {
        public void feed();
    }
    
    public class Dog implements Animal
    {
        public void feed() { ... }
    }
    
    public class Cat implements Animal
    {
        public void feed() { ... }
    }
    
    List<Animal> animals = new ArrayList<>();
    animals.add(new Cat());
    animals.add(new Dog());
    for (Animal animal : animals)
    {
        animal.feed();
    }
    

    在不使用接口的情况下,人们将不得不为每种类型的动物使用单独的逻辑实现来隔离“if-else”(或“switch-case”)。

    • 17
  2. Best Answer
    I. Perevoz
    2020-01-18T17:47:28Z2020-01-18T17:47:28Z

    就我个人而言,理解接口本质的最明显方法是集合以及与它们相关的所有内容。很可能是这样,因为他们必须经常与他们一起工作。

    OOP的主要特征之一是由于正确的架构组件而摆脱了逻辑重复。对于这种情况(一般意义上),发明了接口和抽象类。

    假设我在真空中有一个球形方法,可以对集合进行一些处理:

    /*Здесь может быть любой тип коллекции, который реализует соотв. интерфейс.
    Причем я использую интерфейс самого "низкого" уровня, т.к.
    он полностью покрывает данный функционал (т.е. проход по элементам в цикле)
    Также я могу написать любую свою реализацию для этого интерфейса
    */
    public void showCollectionAtConsole(Iterable<?> col){
       col.forEach(object -> System.out.println(object));
    }
    

    这里的便利之处在于,只有在 Java 本身中,这个接口的实现才相当多,(更多)我可以为它们中的每一个使用这个逻辑。

    现在我有另一种实现某些功能的方法:

    public boolean removeOrAddMyObject (Collection<MyObject> col, MyObject object){
        //Если удалил объект - true, иначе - false
        boolean isRemove = true;
    
        if (col!=null){
            if (col.isEmpty() || !col.remove(object)) {
                col.add(object);
                isRemove = false;
            }
        }else throw new IllegalStateException("Коллекция = null");
    
        return isRemove;
    }
    

    这里我不得不用到三个收集方法:isEmpty()、add()、remove()。但是,所有这些方法都在 Collection 接口中进行了描述,无需传递带有实现作为参数的“更高”接口或类。正如我在上面所写的,这个解决方案将允许我问心无愧地为其他实现重复使用这个方法。

    此外,在我看来,回调是使用接口的一个很好的例子:

    public final class MyClass {
    
        static class MyObject {
            int id;
            String name;
    
            public MyObject(int id, String name) {
                this.id = id;
                this.name = name;
            }
    
            public void setId(int id) {
                this.id = id;
            }
            public void setName(String name){
                this.name = name;
            }
    
            @Override
            public String toString(){
                return "My Object: id = "+id+", name = "+name;
            }
        }
    
        //Интерфейс коллбэка
        interface MyCallback<T extends MyObject> {
            void doSome(T myObject);
        }
    
        
        static void doSomeAwesome(MyObject object, MyCallback<MyObject> callback) {
            System.out.println(object);
            callback.doSome(object);
            System.out.println(object);
        }
    
        public static void main(String[] args) {
    
            MyObject myObject = new MyObject(1,"someName");
    
            MyCallback<MyObject> callback = new MyCallback<MyObject>() {
                @Override
                public void doSome(MyObject myObject) {
                    myObject.setId(2);
                    myObject.setName("someOtherName");
                }
            };
    
            doSomeAwesome(myObject,callback);
        }
    }
    

    最重要的是,在回调接口中,您明确定义了一个泛型(如果您想将参数传递给方法和/或从方法接收对象)并描述契约。在我的例子中,这是一种将参数作为输入的方法。doSomeAwesome()现在,我可以实现我选择的回调方法,从而使用附加逻辑扩展该方法的使用。

    如果执行代码,输出将是:

    我的对象:id=1,name=someName

    我的对象:id=2,name=someOtherName

    UPD: 还应该理解还有其他使用接口的上下文:

    • 多重继承上下文(在 Java 中,您不能继承 1 个以上的类,但可以实现 1 个以上的接口)
    • 接口作为交互实体之间的层。那些。程序中有两个模块,它们执行不同的功能,同时又相互交互。在理想情况下,两个模块都应该代表彼此的“黑盒子”,接口描述的方法最少。因此,在以后调试代码时更容易避免复杂化。
    • 应用程序架构设计上下文。通常,在设计未来应用程序架构的初始阶段,使用接口“估计”实体之间的交互是非常方便的。它就像一个草稿版本,不需要“打扰”实现,并且允许在早期阶段相对轻松地修改架构。
    • 测试上下文。正如其中一个答案中已经提到的,使用接口允许您:“使用模拟对象而不是真实对象”。相信我,从长远来看,这会让生活变得更轻松。
    • 16
  3. Evgeny Mitrokhin
    2020-01-18T14:08:08Z2020-01-18T14:08:08Z

    因为接口是一种抽象,它告诉您做什么,而不是如何做。“生活的简化”在于接口指定了统一的预期行为,无论您在哪里遇到它(当然,除非程序员根本不在乎接口契约)。一般来说,要理解我在这里写的内容,您应该阅读有关 OOP 的书籍。

    • 4
  4. elik
    2020-01-18T13:58:33Z2020-01-18T13:58:33Z

    接口真的让生活更轻松。假设在 android 中我使用一个接口用于导航gps Google api ,一个接口用于监听器(接口几乎无处不在,甚至在流中)并且从 Java-8 开始,接口也实现了主体,所以你不仅可以写条件,还可以写主体接口。但是是否使用它们取决于每个人。实现它们的接口并不总是程序员的责任。

    • 2

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5