代码之家  ›  专栏  ›  技术社区  ›  Andy

向学生解释界面[关闭]

  •  61
  • Andy  · 技术社区  · 15 年前

    几年来,我是一名教学助理,负责编程模块——Java一年级本科生的介绍。

    大多数情况下,它做得很好,我们设法使面向对象的编程很好地传递给学生,但学生很少看到的一件事是接口。

    我们给出的几乎任何解释,要么是因为太做作而对学习没有帮助,要么是因为太脱离了初学者的位置。我们的反应是“我…看,“翻译成”我不懂,听起来也没用。

    这里有没有人能成功地教学生界面?我不再是一个助教了,但总是对我唠叨不休。

    26 回复  |  直到 8 年前
        1
  •  31
  •   Ian Dallas    15 年前

    如果您试图向初学者解释这一点,我会坚持这样一个观点:接口可以促进代码重用和代码中的模块化:

    例如,假设我们要绘制一些对象:

    public class Painter {
        private List<Paintable> paintableObjects;
    
        public Painter(){
           paintableObjects = new ArrayList<Paintable>();
        }
    
        public void paintAllObjects(){
            for(Paintable paintable : paintableObjects){
                paintable.paint();
            }
        }
    }
    
    public interface Paintable {
         public void paint();
    }
    

    现在,您可以向学生解释,如果没有可绘制的界面,则绘制对象需要有方法来绘制某些类型的对象,如调用 paintFences() paintRocks() 我们需要一个新的 Collection 对于每种类型的物体,我们都希望画家能够绘画。

    但值得庆幸的是,我们有一些接口可以让绘制对象变得轻而易举,而对象的绘制方式完全取决于实现可绘制接口的类。

    编辑

    我忘记提到的另一个好处是,如果您需要向代码库中添加要绘制的新对象,那么您所需要做的就是创建一个实现可绘制的新类,而painter类永远不需要更改。从这个意义上说,painter类从不依赖它要绘制的对象,它只需要能够绘制它们。

    编辑2

    JamesRaybould提醒我一个我忘记提到的界面的关键用法:在组件之间有一个界面,比如可绘制对象和绘制对象,可以让你更容易地与其他人一起开发。一个开发人员可以处理painter对象,另一个开发人员可以处理paintable对象,他们要一起正常工作所必须做的就是事先定义一个公共接口,这两个接口都将使用。我知道,当我在大学水平的项目中与其他人一起工作的时候,当你试图让每个人都在项目的不同部分工作,并且最终仍然让所有的组成部分都很好地结合在一起时,这真的很有帮助。

        2
  •  29
  •   aepryus    15 年前

    在向非程序员解释接口和面向对象的概念时,我总是使用家庭娱乐系统类比。

    DVD播放器、电视、有线电视、遥控器都是封装了复杂和复杂功能的对象。然而,它们之间有接口,也有操作它们的人类的接口,这些接口很大程度上隐藏了这种复杂性的大部分。

    电视的视频输入插孔是一个接口,由DVD播放机、有线电视盒和许多其他类型的设备实现。

    我认为学生可以用Java代码来描述他们自己的家庭娱乐系统是可能的,也许是一种教育练习。

        3
  •  16
  •   corsiKa    15 年前

    “当类是某种东西时,接口通常会做一些事情。所以我可能有车,但我不会去“卡林”,但我可能会去开车…所以我的车可能实现“可驾驶”界面。

    编辑:

    马克提出了一个很好的观点。接口根本不做任何事情,而是定义发生了什么行为。而且,他也提出了一个不想混淆观众的好观点。并不是说混淆经验丰富的开发人员是可以的,但混淆一个全新的学生绝对不是一个好主意。有鉴于此,我将把我的一行修改成多行。

    “在类定义存在的地方,接口定义行为。类定义什么是什么,而接口定义什么是什么。所以我可能有一辆车,它有发动机,有多少汽油,它的历史MPG是什么,等等,但我永远不会去“携带”。另一方面,我可能会去开车…我的车能开吗?如果我给它一个驱动方法,它可以。我也可以使用“可驱动”界面和驱动方法,并将其留给汽车来确定驱动真正的含义。现在,如果我只有车的话,拥有一个接口就没什么大不了的了。但是卡车呢?如果它们都可以驾驶,我可以简单地 List<Drivable 对于他们两个。当然,观察型的学生说,“为什么汽车和卡车不能简单地延长车辆,用一个抽象的驾驶方法?”这实际上是一个非常有效的概念。但是,航天飞机呢?汽车和卡车之间很少有部件适用于航天飞机,因此它似乎不适合扩展车辆等级。或者未来的汽车呢?我们不知道他们可能是什么样子,他们可能没有贞操,他们可能只是能量的气泡,让我们四处移动,但我们仍然可以称他们的行为为 drive() ."

    呼吸

    现在,段落/文章有点冗长,但我可以看到,有了一些幻灯片或黑板,对于一年级的学生来说是有效的,让他们有足够的头脑(假设他们首先理解抽象课)。

        4
  •  10
  •   John R Perry    8 年前

    我刚刚解释了一个工作伙伴的接口,她正在学习Java,从一开始她就没有得到所有OOP的东西,所以我只是从一个非软件工程的角度解释了一切,我对接口的解释如下:

    假设你想雇一个管道工来修理你的房子,你不知道(而且你也不太在乎)你最终会雇佣谁,但你知道管道工必须能做什么。所以,你定义了一组任务,任何自称是水管工的人都必须知道该怎么做。当然,每个人都可能有自己的方式来完成每一项任务,但最终,你雇佣的人是一个水管工,因为他们知道如何完成每一项任务。所以,如果你要用Java编写这个,首先要做的是定义一个 interface 像这样的管道工:

    public interface Plumber
    { //silly code here }
    

    好吧,那么,假设我知道如何完成你要求的每项任务,所以我完全符合你的要求,所以根据你的要求,我是一个水管工。所以,今天我决定做你的水管工,而你决定雇佣我(耶!)基于上一个例子,你可以说我是一个知道如何以特定的方式开发软件和管道的人,如果我作为一个类为我编写代码,我可以这样写:

    public class Rick extends Person implements SoftwareDeveloper, Plumber
    

    后来你可以用我当水管工在家里修理东西:

    Plumber thePlumber = rick;
    thePlumber.fixLeak(myHouse.bathroom.leak) // =(
    

    从这一点开始,剩下的OOP概念很容易解释。

        5
  •  8
  •   PaiS    15 年前

    嗯,最近,我碰巧向一个关系密切的人解释了这件事。我解释“为什么是接口”这个问题的方式。,以USB端口和USB驱动器为例。

    USB端口可以被视为一个规范,只要它们实现了规范,任何USB驱动器都可以安装在其中。因此,在这种情况下,端口成为接口,各种类型的USB存储棒可用,成为类。 举个例子,如果我要给某人提供一个USB驱动器(类),我就不需要告诉他们(调用方法)我要传递什么。如果调用方法采用USB驱动器(类类型)作为引用,我将无法传递任何东西,只能传递端口所指向的USB驱动器。

    综上所述,intefaces可以帮助调用者与调用方法兼容(在用例中,当调用方法需要一个特定类型的实例时),无论您通过哪个实例,调用者和被调用者都可以确保它(实例)适合接口引用(用于类比的USB端口)。

        6
  •  7
  •   meriton    15 年前

    类,我们花了最后几个会话来实现快速排序。很难按姓名对名单进行分类。如果你必须按等级分类,你现在会怎么做?如果你必须按年龄对恐龙进行分类,你会怎么做?到目前为止,您唯一知道的方法是复制Quicksort的代码,并更改比较和它所操作的类型。这是可行的——直到你找到那个总是困扰着你的流沙的难以捉摸的虫子,并且必须把它修复成散布在各处的流沙的几十个副本。

    今天,我们将学习更好的方法。

    我们可以编写一个快速排序,而不需要定义列表的排序顺序,并且在调用该快速排序时单独定义该顺序(并且仅定义该顺序)。

    [此处以比较器接口为例,插入接口和多态性机制的解释]

    现在,只有一个Quicksort副本,而bug只需要修复一次。此外,人们可以在不理解的情况下使用QuickSort(或者,如果他们已经理解了QuickSort,则在您想要排序时,不必考虑它的机制)。此外,编写快速排序的人不需要知道您需要排序列表的顺序。因此,接口隔离了两组程序员,允许他们单独开发软件的各个部分。这就是为什么在许多编程语言中,您会在API中找到实现良好并经过测试的排序方法,即使这些方法的程序员不知道人们稍后要排序的所有对象类型和顺序。

        7
  •  6
  •   Thorbjørn Ravn Andersen    15 年前

    我通常使用“合同”,但“郑重承诺”也有助于理解。

        8
  •  5
  •   JRL    15 年前

    我推荐的第一章 Head First Design Pattern 是这样的。Duck模拟解释了使用继承的问题,本章的其余部分将继续解释如何使用继承。

        9
  •  3
  •   YoK    15 年前

    这解释得最好:(引用自此 tutorial )

    在软件工程中,有很多情况下,对于不同的程序员群体来说,同意一个“合同”是很重要的,它可以解释他们的软件是如何交互的。每个组都应该能够编写自己的代码,而不需要知道其他组的代码是如何编写的。一般来说,接口就是这样的契约。 例如,想象一个未来社会,计算机控制的机器人汽车在城市街道上运送乘客,而不需要人工操作。汽车制造商写的软件(Java,当然),运行汽车停止,启动,加速,左转,等等。另一个工业集团,电子制导仪器制造商,制造接收GPS(全球定位系统)位置数据和无线传输交通状况的计算机系统,并使用这些信息来驱动汽车。

    汽车制造商必须发布一个行业标准界面,详细说明可以调用哪些方法来移动汽车(任何汽车,来自任何制造商)。然后,指导制造商可以编写软件,调用接口中描述的方法来指挥汽车。两个工业集团都不需要知道另一个集团的软件是如何实现的。事实上,每个小组都认为自己的软件是高度专有的,并保留随时修改它的权利,只要它继续坚持发布的界面。

    更多链接: http://download-llnw.oracle.com/javase/tutorial/java/concepts/interface.html

        10
  •  2
  •   Philippe A.    15 年前

    理解接口与理解多态性和IS-A关系没有很大的不同。由于通过实现接口或继承基类建立的关系,所有实现相同接口的类都可以由程序作为“基”类型统一操作。

    接口和基类之间的选择是设计决策。我会保持简单。

    • 当实现可以假定类的完整或部分行为时,定义类。
    • 使该类成为抽象类,以指示基类不是完整的实现,不能按原样使用。
    • 如果提供部分实现没有意义,请提供接口而不是基类。

    接口和继承的好处几乎是相同的。接口只是比基类更抽象的类型定义。

    更新

    下面是一个简单的程序,您可以使用它来演示相似的继承和接口。修改程序使基成为接口而不是类。在A类中,将“extends”替换为“implements”。程序的结果将相同。

    ClassB的目的是进一步说明类与其接口/基类之间关系的重要性。类B的一个实例不能传递给processBase,尽管它与base有相似之处,除非我们建立了一个明确的关系。

    abstract class Base {
      public void behavior() {};
    };
    
    class ClassA extends Base {
      public void behavior() {
        System.out.println("ClassA implementation of Base behavior");
      }
    };
    
    class ClassB {
      public void behavior() {
        System.out.println("ClassB's version of behavior");    
      }
    }
    
    public class InterfaceExample {
    
      public void processBase (Base i) {
        i.behavior();
      }
    
      public static void main (String args[]) {
          InterfaceExample example = new InterfaceExample();
          example.processBase(new ClassA());
      }   
    }
    
        11
  •  2
  •   Alain O'Dea    15 年前

    面向接口的设计 比我描述的更好 http://pragprog.com/titles/kpiod/interface-oriented-design . 作者使用了一些很好的界面与继承的例子,比如动物王国的分类法。它有一些最好的理由来反对过度继承和明智地使用我迄今为止读过的接口。

    一堆网站,他们提出的方式不兼容:

    上市 爪哇浏览器 :

    public class Facebook {
        public void showFacebook() {
            // ...
        }
    }
    

    上市 Youtubj.java :

    public class YouTube {
        public void showYouTube() {
            // ...
        }
    }
    

    上市 堆栈溢出.java :

    public class StackOverflow {
        public void showStackOverflow() {
            // ...
        }
    }
    

    一个客户端手动处理网站使用的不同方法 他们自己:

    上市 clientwithout接口.java :

    public class ClientWithoutInterface {
        public static void main(String... args) {
            String websiteRequested = args[0];
            if ("facebook".equals(websiteRequested)) {
                new Facebook().showFacebook();
            } else if ("youtube".equals(websiteRequested)) {
                new YouTube().showYouTube();
            } else if ("stackoverflow".equals(websiteRequested)) {
                new StackOverflow().showStackOverflow();
            }
        }
    }
    

    介绍一个网站界面,使客户的工作更容易:

    上市 爪哇网站 :

    public interface Website {
        void showWebsite();
    }
    

    上市 爪哇浏览器 :

    public class Facebook implements Website {
        public void showWebsite() {
            // ...
        }
    }
    

    上市 Youtubj.java :

    public class YouTube implements Website {
        public void showWebsite() {
            // ...
        }
    }
    

    上市 堆栈溢出.java :

    public class StackOverflow implements Website {
        public void showWebsite() {
            // ...
        }
    }
    

    上市 客户端接口.java :

    public class ClientWithInterface {
        public static void main(String... args) {
            String websiteRequested = args[0];
            Website website;
            if ("facebook".equals(websiteRequested)) {
                website = new Facebook();
            } else if ("youtube".equals(websiteRequested)) {
                website = new YouTube();
            } else if ("stackoverflow".equals(websiteRequested)) {
                website = new StackOverflow();
            }
            website.showWebsite();
        }
    }
    

    哇哦,多点免费的代码?实际上,我们可以走得更远一点, 让客户联系几个朋友来帮助他们找到并提供 请求的网站:

    上市 clientwithalittlehelpfromfriends.java :

    public class ClientWithALittleHelpFromFriends {
        public static void main(String... args) {
            WebsiteFinder finder = new WebsiteFinder();
            WebsiteRenderer renderer = new WebsiteRenderer();
            renderer.render(finder.findWebsite(args[0]));
        }
    }
    

    上市 网站查找器.java :

    public class WebsiteFinder {
        public Website findWebsite(String websiteRequested) {
            if ("facebook".equals(websiteRequested)) {
                return new Facebook();
            } else if ("youtube".equals(websiteRequested)) {
                return new YouTube();
            } else if ("stackoverflow".equals(websiteRequested)) {
                return new StackOverflow();
            }
        }
    }
    

    上市 网站渲染器.java :

    public class WebsiteRenderer {
        public void render(Website website) {
            website.showWebsite();
        }
    }
    

    回望 客户端没有接口 它完全耦合到特定的查找和基于渲染的查找。当你访问成百上千的网站时,很难进行管理。与 网站 接口就位 网站管理员 可以很容易地转换为在地图、数据库甚至基于Web的查找上进行备份,以满足不断增长的规模。

    接口使得将角色与实现角色的组件分离成为可能。它们可以基于几乎所有的东西来交换相同问题的替代解决方案:

    • 机器上的电流负载

    • 数据集的大小(可以选择排序算法)

    • 请求执行操作的用户

        12
  •  2
  •   JulesLt    15 年前

    我打这个是为了评论Harima555s的回答,但它扩大了。我想知道从另一端开始是否更有意义——让他们先了解接口是如何有用的,然后再讨论如何编写接口。

    假定他们很好地掌握了继承、多态性和抽象类。我可能会先回顾一下抽象课,让其中一个学生解释一下。

    接下来,介绍一个带有接口的类的示例,以了解角色/契约的概念。为了简化事情,从一个超类开始。

    public class Rick extends Person implements SoftwareDeveloper, Plumber
    public class Zoe  extends Person implements SoftwareDeveloper, Chef
    public class Paul extends Person implements Plumber, Chef
    public class Lisa extends Person implements Plumber
    

    不要解释得太多,但是试着让学生理解语法的含义——也许显示一些引用管道工或软件开发人员的代码。

    问他们如何利用人的继承来实现同样的事情。他们应该很快陷入困境,或者提出多重继承。为了避免以后再讨论菱形问题,假设角色中没有重叠的方法。

    接下来,我将尝试克服这样一个想法:同一个接口可以用于不同类型的类。

    public class Plane extends Vehicle implements Fly, PassengerTransport, Serviceable
    public class Train extends Vehicle implements PassengerTransport, Serviceable
    public class Bird  extends Animal  implements Fly
    

    同样,尝试让他们考虑如何使用公共超类和重写实现相同的事情。

    然后说明如何使用接口而不是类来编写多态代码——比如说一个为过路人交易门票的Travelagent。细想一下这一点的优势——你可以编写在不同层次的类上工作的多态代码。

    在这一点上,他们可能会有这样的错觉:一个接口非常类似于能够向一个类添加另一个超类,并且将掌握多重继承的优势。

    所以现在我们必须通过理解菱形问题来解释为什么这会使事情复杂化,并且接口没有默认的实现。

    回到第一个例子,让他们研究一下如果软件开发者和水管工都有一个“makedrink”方法(一个制造可乐,另一个制造咖啡),我们对rick执行makedrink。

    试着推动某人去考虑这样一个想法,即如果在两个“超级杯”中保持饮料的抽象,问题就消失了。在这一点上,已经有了概念性的一面,我们应该准备好讨论定义接口的语法。

    (我确实考虑过引入第二个原因——编写可应用于不同类层次结构的通用代码的困难,但发现最终会出现“为什么不能从接口继承高度属性”或过早地讨论通用编程)。

    我想现在我们应该通过MICKEY鼠标例子来覆盖这些概念,然后你可以通过解释正确的技术术语,并从Java API中使用真实世界的例子。

    • 当他们试图学习Java/接口时,我不想让人迷惑,但是一旦他们得到了它,就值得指出其他OO语言对同一个问题采取不同的方法,从多重继承到鸭子打字——如果他们感兴趣的话,他们应该研究它们。
        13
  •  1
  •   BalusC    15 年前

    你也教JDBC吗?以它为例。这是一个很好的现实世界中界面功能强大的例子。在JDBC中,您编写的代码是针对几乎只存在接口的API的。JDBC驱动程序是具体的实现。您可以很容易地在许多数据库上重用JDBC代码,而无需重写代码。您只需切换JDBC驱动程序实现JAR文件和驱动程序类名,就可以让它在另一个数据库上工作。

    至少,使用接口可以在某种方式/点上从具体实现(负责行为的代码逻辑)更改,而无需重写整个代码。在解释事情时,尽量用现实世界的例子。这会更有意义。

        14
  •  1
  •   Grzegorz Gajos    15 年前

    我最近发现了一种非常有用的使用界面的方法。

    我们有很多东西…

    public class Settings { String[] keys; int values; }
    public class Car { Engine engine; int value; }
    public class Surface { int power; int elseInt; }
    // and maaany more (dozens...)
    

    现在,有人正在创建(即)表,希望显示所有对象列表中的一些对象,但要在列表中显示对象,他必须编写返回字符串[]的方法。

    String[] toArrayString()
    

    所以他只是在表中需要的所有类中实现这个方法

    public class Settings { String[] keys; int values; public String[] toArrayString {...} }
    public class Car { Engine engine; int value; } // THIS NOT
    public class Surface { int power; int elseInt; public String[] toArrayString {...} }
    // and maaany more (dozens...)
    

    现在,当他创建表时,他正在这样写smth

    public void createTable() {
        for(Object obj : allObjects) {
           if(obj instanceof Settings) {
              Settings settings = (Settings)obj;
              table.add(settings.toArrayString());
           }
           if(obj instanceof Surface) {
              // cast...
           }
           // etc multiple times...
        }
    }
    

    通过接口,此代码可以更短、更易于读取和维护:

    public interface ISimpleInterface { String[] toArrayString; }
    
    public class Settings implements ISimpleInterface { String[] keys; int values; public String[] toArrayString {...} }
    public class Car { Engine engine; int value; } // THIS NOT
    public class Surface implements ISimpleInterface { int power; int elseInt; public String[] toArrayString {...} }
    
    public void createTable() {
        for(Object obj : allObjects) {
           if(obj instanceof ISimpleInterface) {
              ISimpleInterface simple = (ISimpleInterface)obj;
              table.add(simple.toArrayString());
           }
        }
    }
    

    此外,我们可以在不进行任何派生的情况下以非常干净和有效的方式实现多个接口(派生有时是不可能的,不仅是在类已经在使用某种其他派生的情况下)。

        15
  •  0
  •   Jesus Ramos    15 年前

    接口提供了一个类需要做的事情,例如,你可以有一个动物接口,让我们假设它有一个名为speak()的方法,每个动物都可以说话,但它们都有不同的做法,但这允许你将实现动物对动物的任何东西进行强制转换,这样你就可以有一个动物列表,让它们都说话,但使用它们的OW。n实施。接口只是这些东西的包装器。

        16
  •  0
  •   Community Mohan Dere    9 年前

    在前面的这个问题中,有一些很好的场景解释了接口使用背后的原因。

    Stack Overflow Question

        17
  •  0
  •   SargeATM    15 年前

    接口的真正价值在于能够覆盖第三方API或框架中的组件。我将构建一个作业,在这个作业中,学生需要覆盖预先构建的库中他们无法更改的功能(并且没有其源)。

    更具体地说,假设您有一个“框架”,它生成一个作为页面类实现的HTML页面。和page.render(stream)生成HTML。假设该页以 密封的 ButtonTemplate类。ButtonTemplate对象有自己的呈现方法,因此在page.render(stream)buttonTemplate.render(label,stream)中,只要有按钮,就会调用该对象,并为提交按钮生成HTML。作为学生的一个例子,假设我们想用链接替换那些提交按钮。

    除了描述最终的输出,我不会给他们太多的指导。他们将不得不尝试各种各样的解决方案。 “我们是否应该尝试解析按钮标签并用定位标签替换?我们能将buttonTemplate子类化吗?哦,等等。它是密封的!他们封课的时候在想什么??! 然后,在该分配之后,用带有render(label,stream)方法的ILabledTemplate接口显示第二个框架。

        18
  •  0
  •   Hut8    15 年前

    除了其他的答案,你可以尝试从不同的角度来解释它。我确信学生们已经知道了遗传,因为它可能被每一个Java学生的喉咙压下。他们听说过多重继承吗?方法解析被视为C++中的一个设计问题(也在Perl和其他多继承语言中),因为概念上,当在两个基类中定义的子类中调用一个方法时,它究竟应该发生什么,这一点是模棱两可的。都被处决了吗?哪一个先?一个可以被具体引用吗?也见 diamond problem . 我的理解是,这种混淆仅仅通过引入没有实现的接口来解决,所以在方法解析过程中使用哪种实现是不含糊的。

        19
  •  0
  •   supercat    15 年前

    如果一个类需要精确地处理 抽象功能,以及 不需要继承任何其他类 可以使用抽象类来公开功能,然后从中派生真正的类。不过,请注意这两个斜体字。接口使得一个类可以表现为几个独立的抽象事物类型,即使这个类是从另一个不表现为这些事物类型的类派生出来的。因此,接口满足多重继承的主要使用情形之一,而不需要伴随多重继承而产生的麻烦。

    一个非常实用的界面的简单现实例子:IEnumerable。如果一个类拥有某种类型的任意数量的项,那么对于另一个类来说,在不必担心拥有这些项的对象的细节的情况下,对所有这些项都起作用是非常有用的。如果“EnumerableThing”是一个抽象类,那么从非“EnumerableThing”派生的任何类的对象都不可能传递给期望为EnumerableThing的代码。由于任何类(包括派生类)都可以实现EnumerableThing,而不考虑基类是否这样做,因此可以向任何类添加枚举功能。

        20
  •  0
  •   Icemanind    15 年前

    很久以前,我读过一本书(虽然记不起它的名字),它对接口有一个很好的类比。如果你(或你的学生)去过一家冰激凌店,这听起来会很熟悉。冰激凌有冰激凌,你可以在冰激凌中加入一些不同的东西(在冰激凌中被称为混入)。这些混入将类似于接口。您的类(或冰淇淋)可以有任意多的接口(或混合输入)。添加一个接口(或混入)会将该接口(或混入)的内容(或味道)添加到您的类(或冰淇淋)中。希望这有帮助!

        21
  •  0
  •   LostMohican    15 年前

    契约是关于接口的第一个知识,但是它们是在语言中构建的,以提供多重继承的技能,并避免多重继承的复杂性。因此,您可以教他们接口将运行时行为添加到程序中,或者告诉学生可以使用接口更改对象的运行时行为。

        22
  •  0
  •   Philippe Carriere    15 年前

    首先,学生必须掌握抽象概念。 当你(学生们)看到一个老师时,你可以把他描述成一个老师… 你也可以把他描述成(学校的)雇员。 你可以把他描述成一个人。 你三次都是对的。这些是你可以给他的“头衔”。

    他是一个老师,一个计算机科学老师,同样的数学老师也是一个老师。 它们在相同的抽象层次上。 现在教师是雇员,就像看门人是雇员一样。 它们在相同的抽象层次上。 就业者是一个人,就像失业者是一个人一样。 它们在相同的抽象层次上。

    (以UML的方式在板上绘制整个东西)。

    这就是将(粗略地)描述科学教师在社会中的地位的架构。

    现在抽象的层次定义了一组共同的对象有什么共同点:所有的老师教给他们的学生,并创建不可能的考试问题,以确保他们失败。学校的所有雇员都为学校工作。

    在编程中,接口是一个抽象级别。它描述了一组对象可以完成的操作。 每个对象都有一种独特的操作方式,但操作类型是相同的。

    以一些乐器为例:钢琴、吉他和长笛。 他们有什么共同点?音乐家可以演奏它们。 你不能让音乐家吹这三种乐器,但你可以让他演奏。

    整个概念的架构如下:

    接口(它们的共同点)是工具。因为它们都是工具:这是它们共同拥有的抽象概念。 他们有什么共同点?玩。所以你定义了一个称为play的抽象方法。

    现在你不能定义“乐器”将如何演奏,因为它取决于乐器的类型。 长笛是一种乐器。所以班上的长笛演奏乐器。 现在,您必须定义音乐家在演奏这种类型的乐器时要做什么。 所以你要定义播放方法。此定义将覆盖仪器的定义。 其他两种仪器也要这样做。

    现在,如果你有一个乐器列表,但不知道它们是什么类型的,你仍然可以“要求”它们演奏。 每个长笛都会吹响。 每把吉他都会被刮伤。 每架钢琴都是…呵呵。。。钢琴曲?无论什么!

    但每个对象都知道如何执行“play”操作。你不知道它们是什么样的乐器,但既然你知道它们是乐器,你就要求它们演奏,它们知道如何演奏。

        23
  •  0
  •   Eno    15 年前

    您还可能希望将Java中的接口与C++进行比较和对比(最终使用多继承和/或“朋友”类)。

    (至少,对我来说,这说明了在爪哇有多么简单/简单的接口:

        24
  •  0
  •   hvgotcodes    15 年前

    我会告诉他们“接口定义 什么 提供“行为”和“实现提供这些行为”。使用接口的代码不需要 怎样 事情正在发生,只需要知道 什么 事情可能会发生。

    一个很好的例子是DAO模式。它定义了“保存”、“加载”、“删除”等行为。您可以有一个与数据库一起工作的实现,以及一个转到文件系统的实现。

    我认为到目前为止,很多其他的答案对于那些没有马上得到答案的学生来说太复杂了…

        25
  •  0
  •   weiy    15 年前

    我认为,一般来说,实践学习总是有助于强化讲课后的概念和例子。因此,正如梅里顿所建议的,我将呈现同一程序的两个版本。(快速排序是一个很好的例子)

    让学生对每个程序进行多次修改,找出程序中的细微缺陷,以便他们修复。我认为,你的学生很快就会发现,在设计一个程序时,界面提供了许多优势,而他们必须在以后修改它!

        26
  •  0
  •   Enno Shioji    15 年前

    我总是认为它是一种尽可能少地(口头)交流的手段,因为(良好的交流)是软件工程中最困难的事情。对于Web服务和SOA也是如此。如果你给某人一个接口,然后说“请提供这个服务”。这是一个非常方便的方法,因为你不需要解释太多,编译器会检查他们是否做了正确的工作,而不是你!(我的意思是,不是真的,但至少它能确保方法的存在)。