Объяснение интерфейсов [закрытым] студентам

В течение нескольких лет я был обучающим помощником по введению в программный модуль - Java для первых студентов года.

Главным образом это подходило, и нам удалось объяснить объектно-ориентированное программирование студентам вполне хорошо, но одной вещью, из которой студенты редко видели точку, были интерфейсы.

В значительной степени любое объяснение мы дали или произвели впечатление так же слишком изобретенный, чтобы быть полезными для изучения или слишком далеко удаленные из их положения как новички. Реакция, которую мы были склонны получать, была, "я... вижу", перевел как, "Я не понимаю, и они не звучат полезными".

У кого-либо здесь есть способ успешно обучающих студентов об интерфейсах? Я больше не обучающий помощник, но он всегда ворчится на меня.

62
задан Andy 26 August 2013 в 14:12
поделиться

26 ответов

Если вы пытаетесь объяснить это новичкам, я бы придерживался идеи, что интерфейсы могут способствовать повторному использованию кода и модульности внутри кода:

Например, допустим, мы собираемся рисовать некоторые объекты:

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();
}

Теперь вы можете объяснить студентам, что без интерфейса Paintable объект Painter должен иметь методы для раскрашивания определенных типов объектов, например, метод под названием paintFences() и paintRocks(), и нам нужно будет иметь новую Collection для каждого типа объектов, которые мы хотим, чтобы художник мог раскрашивать.

Но, к счастью, у нас есть интерфейсы, которые делают рисование объектов простым делом, и то, как объекты будут рисоваться, полностью зависит от классов, реализующих интерфейс Paintable.

EDIT

Еще одно преимущество, о котором я забыл упомянуть, заключается в том, что если вам когда-нибудь понадобится добавить новый объект для рисования в вашу кодовую базу, все, что вам нужно сделать, это создать новый класс, реализующий Paintable, и класс Painter никогда не придется менять. В этом смысле класс Painter никогда не зависит от объектов, которые он собирается рисовать, ему нужно только уметь их рисовать.

EDIT 2

Джеймс Рэйбоулд напомнил мне о ключевом использовании интерфейсов, о котором я забыл упомянуть: Наличие интерфейса между вашими компонентами, такими как объекты Paintable и Painter, позволяет вам легче разрабатывать вместе с другими людьми. Один разработчик может работать над объектами Painter, а другой - над объектами Paintable, и все, что им нужно сделать для правильного функционирования вместе, - это заранее определить общий интерфейс, который они оба будут использовать. Я знаю, когда я работал над проектами с другими людьми на уровне колледжа, это очень помогает, когда вы пытаетесь заставить всех работать над разными частями проекта, но при этом все компоненты в итоге должны быть хорошо собраны вместе.

31
ответ дан 24 November 2019 в 16:44
поделиться

Я только что объяснил интерфейсы партнеру по работе, она изучала Java на ходу, и она действительно не понимала всего ООП вначале, поэтому я просто объяснил все, начиная с инженерии, не связанной с программным обеспечением с точки зрения моего объяснения интерфейсов, где что-то вроде этого:

Предположим, вы хотите нанять сантехника, чтобы починить некоторые вещи в вашем доме, вы не знаете (и вам все равно), кем вы можете оказаться нанимаете, но вы знаете, что водопроводчик должен уметь. Итак, вы определяете набор задач, которые должен знать каждый, кто утверждает, что он сантехник. Конечно, у каждого может быть свой способ выполнения каждой задачи, но, в конце концов, человек, которого вы нанимаете, будет водопроводчиком, потому что он знает, как выполнять каждую задачу.Итак, если бы вы написали это на java, первое, что нужно было бы сделать, это определить интерфейс сантехника следующим образом:

public interface Plumber
{ //silly code here }

Хорошо, тогда допустим, что я знаю, как выполнять каждую задачу, которую вы выполняете. запрашиваю и поэтому я полностью соответствую вашим требованиям, и поэтому, по вашему мнению, я сантехник. Итак, сегодня я решил стать вашим водопроводчиком, и вы решили нанять меня (ура!), Основываясь на последнем примере, вы можете сказать, что я человек, который знает, как разрабатывать программное обеспечение и сантехнику определенным образом, если я должны были написать код для меня как класса, я мог бы написать что-то вроде этого:

public class Rick extends Person implements SoftwareDeveloper, Plumber

а позже вы могли бы исправить вещи в своем доме, используя меня как своего сантехника:

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

с этого момента оставшиеся концепции ООП было легко объяснить .

11
ответ дан 24 November 2019 в 16:44
поделиться

Я рекомендую для этого первую главу Head First Design Pattern s. Симуляция Duck объясняет проблему использования наследования, а остальная часть главы объясняет, как это сделать.

5
ответ дан 24 November 2019 в 16:44
поделиться

Ну, недавно мне довелось объяснять это кому-то близкому. Я объяснил вопрос «Почему именно интерфейсы?» На примере USB-порта и USB-накопителей.

Порт USB можно рассматривать как спецификацию, и в него может поместиться любой USB-накопитель при условии, что они соответствуют спецификации. Таким образом, в этом случае порт становится интерфейсом, а многочисленные типы доступных USB-накопителей становятся классом. Продолжая этот пример, если бы я снабдил кого-нибудь USB-накопителем (классом), мне не пришлось бы сообщать им (вызывающему методу), что я передаю. Если бы вызывающий метод использовал USB-накопитель (тип класса) в качестве ссылки, я бы не смог передать ничего, кроме USB-накопителя, для которого предназначен порт.

Подводя итог, можно сказать, что интерфейсы помогают вызывающей стороне быть совместимой с вызывающим методом (в случае использования, когда вызывающий метод ожидает экземпляр определенного типа), независимо от того, какой экземпляр вы передаете, вызывающий также поскольку вызываемый абонент уверен, что он (экземпляр) вписывается в ссылку на интерфейс (порт USB для аналогии).

8
ответ дан 24 November 2019 в 16:44
поделиться

«Там, где классы ЯВЛЯЮТСЯ чем-то, обычно интерфейсы ДЕЛАЮТ что-то. Так что у меня может быть машина, но я бы никогда не стал« тащиться », но я мог бы поехать за рулем ... чтобы моя машина могла реализовать« управляемый »интерфейс.»

РЕДАКТИРОВАТЬ:

Марк поднимает хороший вопрос. Интерфейсы вообще ничего не делают, а вместо этого определяют, какое поведение происходит. И он также поднимает хороший момент о том, что не хочет сбивать с толку публику. Не то, чтобы сбивать с толку опытных разработчиков, но определенно не стоит сбивать с толку новенького студента. В свете этого я превращаю однострочник в многострочный.

«Там, где классы определяют существование, интерфейсы определяют поведение. Классы определяют, что есть что-то, а интерфейсы определяют, что что-то делает. Так что у меня может быть машина, и в ней есть такие вещи, как Двигатель, сколько в ней бензина, что это за история. MPG есть и тому подобное, но я бы никогда не стал «тащить». С другой стороны, я мог бы поехать за рулем ... может ли моя машина водить? Может, если я использую метод Drive. Я также могу иметь «Driveable» "взаимодействовать с методом вождения, и оставьте его на усмотрение автомобиля, чтобы определить, что на самом деле означает вождение. Теперь, если у меня есть только автомобили, не имеет большого значения иметь интерфейс. Но как насчет грузовиков? Если они оба являются управляемыми, я может просто иметь List для них обоих. Конечно, наблюдательный студент говорит: «Почему и Car, и Truck не могут просто расширить Vehicle с помощью абстрактного метода Drive?» Что на самом деле является очень верное понятие.Но как насчет космического шаттла? Очень немногие компоненты между Car и Truck применимы к Space Shuttle, поэтому он не кажется подходящим для расширения класса Vehicle. А как насчет машин будущего? Мы понятия не имеем, на что они могут быть похожи, у них может не быть шассисов, они могут быть просто пузырями энергии, которые нас двигают, но мы все равно можем называть их поведение драйвом () ».

выдыхает.

Теперь этот абзац / эссе немного многословен, но я мог видеть, с помощью нескольких слайдов или классной доски, как они эффективны для студентов первого года обучения (при условии, что они сначала понимают абстрактные классы).

16
ответ дан 24 November 2019 в 16:44
поделиться

Интерфейсы позволяют взглянуть на то, что должен делать класс, например, у вас может быть интерфейс Animal и, допустим, у него есть метод под названием speak (), каждое животное может говорить, но все они это делают. это по-другому, но это позволяет вам преобразовать все, что реализует животное в животное, чтобы вы могли иметь список животных и заставить их всех говорить, но использовать свою собственную реализацию. Интерфейсы - это просто оболочки для таких вещей.

0
ответ дан 24 November 2019 в 16:44
поделиться

Вы также преподаете JDBC? Возьмите это как пример. Это отличный реальный пример того, насколько мощны интерфейсы. В JDBC вы пишете код для API, который существует почти только из интерфейсов. Драйвер JDBC - это конкретная реализация. Вы можете легко повторно использовать код JDBC во многих БД, не переписывая код. Вам просто нужно переключить JAR-файл реализации драйвера JDBC и имя класса драйвера, чтобы заставить его работать с другой БД.

По крайней мере, использование интерфейсов дает вам возможность изменить конкретную реализацию (логику кода, которая отвечает за поведение) в какой-то момент / момент без перезаписи всего кода. При объяснении старайтесь использовать примеры из реального мира. В этом было бы больше смысла.

1
ответ дан 24 November 2019 в 16:44
поделиться

Я набирал это как комментарий к ответу Harima555, но он расширился. Я подумал, имеет ли смысл начать с другого конца - дать им почувствовать, насколько полезны интерфейсы, прежде чем переходить к тому, как вы их пишете.

Предполагается, что они хорошо разбираются в наследовании, полиморфизме и абстрактных классах. Я бы, вероятно, начал с обзора абстрактных классов, попросив одного из студентов объяснить их.

Затем представьте пример классов с интерфейсами, чтобы обойти концепцию ролей / контрактов. Чтобы упростить задачу, начните с одного суперкласса.

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

Не объясняйте это слишком подробно, но попытайтесь заставить учащегося проработать то, что может означать синтаксис - возможно, показывая какой-то код, который ссылается на сантехника или разработчика программного обеспечения.

Спросите их, как они могли бы достичь того же, используя наследование от Person. Они должны довольно быстро застрять или придумать множественное наследование. Чтобы не обсуждать проблему алмаза на потом, скажите, что в ролях нет перекрывающихся методов.

Затем я бы попытался отказаться от идеи, что один и тот же интерфейс может использоваться для разных типов классов.

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, который продает билеты для PassengerTransport.Обратите внимание на силу этого - то, что вы можете писать полиморфный код, который работает с классами из разных иерархий.

На этом этапе они, вероятно, должны быть в иллюзии, что интерфейс во многом похож на возможность добавить еще один суперкласс к классу, и они осознают преимущества множественного наследования.

Итак, теперь мы должны объяснить, почему это все усложняет, а интерфейсы не имеют реализации по умолчанию, путем понимания проблемы ромба.

Вернитесь к первому примеру, попросите их проработать то, что произойдет, если SoftwareDeveloper и Plumber у обоих есть метод MakeDrink (один делает колу, другой - кофе), и мы выполняем MakeDrink на Рике.

Попытайтесь подтолкнуть кого-нибудь к рассмотрению идеи о том, что если MakeDrink остается абстрактным в обоих «суперклассах», проблема исчезнет. На этом этапе, получив концептуальную сторону, мы должны быть готовы рассмотреть синтаксис для определения интерфейса.

(Я подумал о том, чтобы ввести вторую причину - сложность написания универсального кода, который можно было бы применить к разным иерархиям классов, но обнаружил, что в конечном итоге вы получаете «ну почему вы не можете наследовать атрибут высоты от интерфейса» или слишком рано обсуждать универсальное программирование).

Я думаю, что к настоящему времени мы должны были охватить концепции с помощью примеров с Микки Маусом - и затем вы могли бы вернуться к объяснению правильной технической терминологии и использовать реальные примеры из Java API.

  • Я бы не хотел сбивать людей с толку, когда они пытаются изучить Java / интерфейсы, но, как только они это получат, стоит отметить, что другие объектно-ориентированные языки используют разные подходы к той же проблеме, из-за множественного наследования. для утиного набора текста - и если они заинтересованы, они должны изучить их.
2
ответ дан 24 November 2019 в 16:44
поделиться

Вы также можете сравнить и сопоставить интерфейсы в Java с C ++ (где вы в конечном итоге используете множественное наследование и / или «дружественные» классы).

(По крайней мере, для меня это показало, насколько проще / проще интерфейсы в Java: -)

0
ответ дан 24 November 2019 в 16:44
поделиться

Давным-давно я читал книгу (не могу вспомнить ее название), и в ней была довольно хорошая аналогия для интерфейсов. Если вы (или ваши студенты) когда-нибудь ходили в магазин мороженого Cold Stone Creamery, это покажется вам знакомым. В Cold Stone есть мороженое, а в мороженое можно добавить несколько разных вещей (в Cold Stone они называются микс-ин). Эти добавки можно сравнить с интерфейсами. Ваш класс (или мороженое) может иметь столько интерфейсов (или mix-ins), сколько вы захотите. Добавление интерфейса (или микс-ин) добавит содержимое (или вкус) этого интерфейса (или микс-ин) в ваш класс (или мороженое). Надеюсь, это поможет!

0
ответ дан 24 November 2019 в 16:44
поделиться

В дополнение к другим ответам вы можете попытаться объяснить это с другой точки зрения.Я уверен, что студенты уже знают о наследовании, потому что оно забито в глотке каждому студенту, изучающему Java, вероятно, с первой лекции. Слышали ли они о множественном наследовании? Разрешение метода рассматривалось как проблема дизайна в C ++ (а также в Perl и других языках множественного наследования), потому что концептуально неясно, что именно должно происходить, когда метод вызывается в подклассе, который определен в двух его базовых классах. Оба казнены? Что идет первым? Можно ли конкретно сослаться на него? См. Также алмазную задачу . Насколько я понимаю, эта путаница была разрешена простым введением интерфейсов, у которых нет реализации, поэтому нет никакой двусмысленности относительно того, какую реализацию использовать во время разрешения метода.

0
ответ дан 24 November 2019 в 16:44
поделиться

Настоящая ценность интерфейсов заключается в возможности переопределения компонентов в сторонних API или фреймворках. Я бы разработал задание, в котором студентам нужно переопределить функциональность в предварительно созданной библиотеке, которую они не могут изменить (и не имеют исходных текстов).

Чтобы быть более конкретным, допустим, у вас есть "фреймворк", который генерирует HTML-страницу, реализованную в виде класса Page. А page.render(stream) генерирует html. Предположим, что Page принимает экземпляр класса sealed ButtonTemplate. Объект ButtonTemplate имеет свой собственный метод render, так что в page.render(stream) buttonTemplate.render(label,stream) вызывается везде, где есть кнопка, и генерирует html для кнопки submit. В качестве примера для студентов, предположим, что мы хотим заменить эти кнопки отправки на ссылки.

Я бы не давал им особых указаний, кроме описания конечного результата. Им придется ломать голову, пробуя различные решения. "Должны ли мы попытаться разобрать теги кнопок и заменить их тегами якорей? Можем ли мы подкласс ButtonTemplate, чтобы сделать то, что мы хотим? О, подождите. Он же запечатан! О чем они думали, когда запечатывали этот класс!?!" Затем после этого задания покажите второй фреймворк с интерфейсом ILabeledTemplate с методом render(label,stream).

0
ответ дан 24 November 2019 в 16:44
поделиться

В последнее время я нашел очень полезный метод использования интерфейса.

У нас есть много объектов...

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[].

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...)

Теперь, когда он создает таблицу, он пишет что-то вроде этого

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());
       }
    }
}

Более того, мы можем реализовать несколько интерфейсов очень чистым и эффективным способом без какой-либо деривации (деривация иногда невозможна, и не только в случае, когда класс уже использует какую-то другую деривацию).

1
ответ дан 24 November 2019 в 16:44
поделиться

Интерфейсно-ориентированный дизайн описывает это лучше, чем я когда-либо мог http://pragprog.com/titles/kpiod/interface-orarded-design . Автор использует отличные примеры интерфейсов вместо наследования для таких вещей, как систематика животного мира. В нем есть одни из лучших аргументов против чрезмерного наследования и разумного использования интерфейсов, которые я читал на сегодняшний день.

Куча веб-сайтов с несовместимыми способами их вызова:

Список Facebook.java :

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

Список YouTube.java :

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

Список StackOverflow.java :

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

Клиент вручную обрабатывает различные методы, которые веб-сайты используют для вывода сами вверх:

Листинг ClientWithoutInterface.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();
        }
    }
}

Представьте интерфейс веб-сайта, чтобы облегчить работу клиента:

Список Website.java :

public interface Website {
    void showWebsite();
}

Листинг Facebook.java :

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

Листинг YouTube.java :

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

Список StackOverflow.java :

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

Листинг ClientWithInterface.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]));
    }
}

Список WebsiteFinder.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();
        }
    }
}

Список WebsiteRenderer.java :

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

Оглядываясь назад на ClientWithoutInterface , он полностью связан как с конкретным поиском, так и с рендерингом. Было бы очень сложно управлять, когда вы попадаете на сотни или тысячи сайтов. С помощью интерфейса веб-сайта можно легко преобразовать WebsiteFinder для поддержки на карте, в базе данных или даже для поиска в Интернете для удовлетворения возрастающих масштабов.

Интерфейсы позволяют отделить роль от компонента, который ее выполняет. Они позволяют заменять альтернативные решения той же проблемы на основе чего угодно:

  • Текущая нагрузка на машину

  • Размер набора данных (можно выбрать алгоритмы сортировки)

  • Пользователь, запрашивающий выполняемое действие

2
ответ дан 24 November 2019 в 16:44
поделиться

Понимание интерфейсов не сильно отличается от понимания полиморфизма и отношений IS-A. Все классы, реализующие один и тот же интерфейс, могут управляться программой единообразно как «базовый» тип из-за связи, установленной путем реализации интерфейса или наследования базового класса.

Выбор между интерфейсом и базовым классом - это дизайнерское решение. Я бы сделал это просто.

  • Определите класс, когда ваша реализация может предполагать полное или частичное поведение класса.
  • Сделайте этот класс абстрактным, чтобы указать, что базовый класс не является полной реализацией и не может использоваться как есть.
  • Предоставьте интерфейс вместо базового класса, если нет смысла предоставлять частичную реализацию.

Преимущества интерфейсов и наследования почти одинаковы. Интерфейс - это просто более абстрактное определение типа, чем базовый класс.

Обновление

Вот простая программа, которую вы можете использовать, чтобы продемонстрировать схожесть наследования и интерфейсов. Измените программу, чтобы сделать Base интерфейсом вместо класса. В ClassA замените «расширяет» на «орудия». Результат программы будет таким же.

Цель ClassB - дополнительно проиллюстрировать важность взаимосвязи между классом и его интерфейсом / базовым классом. Экземпляр ClassB не может быть передан в 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());
  }   
}
2
ответ дан 24 November 2019 в 16:44
поделиться

Это объясняет лучше всего : (ссылка на этот учебник)

В программной инженерии существует ряд ситуаций, когда для разрозненных групп программистов важно договориться о "контракте", в котором прописано, как взаимодействует их программное обеспечение. Каждая группа должна иметь возможность писать свой код без каких-либо знаний о том, как написан код другой группы. Вообще говоря, интерфейсы - это такие контракты. Например, представьте себе футуристическое общество, где роботизированные автомобили с компьютерным управлением перевозят пассажиров по городским улицам без участия человека-оператора. Производители автомобилей пишут программное обеспечение (конечно, на Java), которое управляет автомобилем - останавливает, запускает, ускоряет, поворачивает налево и так далее. Другая промышленная группа, производители приборов электронного наведения, создают компьютерные системы, которые получают данные о местоположении по GPS (Глобальная система позиционирования) и беспроводную передачу информации о дорожной обстановке и используют эту информацию для управления автомобилем.

Производители автомобилей должны опубликовать стандартный для отрасли интерфейс, в котором подробно описано, какие методы могут быть вызваны, чтобы заставить автомобиль двигаться (любой автомобиль, любого производителя). Затем производители систем управления могут написать программное обеспечение, которое вызывает методы, описанные в интерфейсе, для управления автомобилем. Ни одной из промышленных групп не нужно знать, как реализовано программное обеспечение другой группы. Фактически, каждая группа считает свое программное обеспечение исключительно собственным и оставляет за собой право изменять его в любое время, пока оно продолжает придерживаться опубликованного интерфейса.

Дополнительная ссылка: http://download-llnw.oracle.com/javase/tutorial/java/concepts/interface.html

3
ответ дан 24 November 2019 в 16:44
поделиться

Я обычно использую "контракт", но "торжественно обещает предоставить" тоже может помочь пониманию.

6
ответ дан 24 November 2019 в 16:44
поделиться

Класс, последние несколько занятий мы потратили на реализацию сортировки. Было трудно отсортировать список "Лица" по имени. Что бы вы сейчас сделали, если бы вам пришлось сортировать этот список по классу? А что бы вы сделали, если бы вам нужно было отсортировать список динозавров по возрасту? Единственный способ, который вы пока знаете, - это скопировать код quicksort, изменить сравнение и типы, над которыми оно работает. Это будет работать - пока вы не найдете неуловимую ошибку, которая всегда мучила ваш quicksort, и вам придется исправлять ее в нескольких десятках копий этого quicksort, разбросанных повсюду.

Сегодня мы познакомимся с лучшим способом.

Мы можем написать квиксорт без определения порядка, в котором мы хотим отсортировать список, и определить этот порядок (и только его) отдельно, когда мы вызываем этот квиксорт.

[ вставить объяснение механики интерфейсов и полиморфизма, используя интерфейс Comparator в качестве примера, здесь ]

Теперь существует только одна копия quicksort, и ошибки нужно исправлять только один раз. Кроме того, люди могут использовать quicksort, не понимая его (или, если они его поняли, не задумываясь о его механике всякий раз, когда нужно что-то отсортировать). Кроме того, людям, написавшим quicksort, не нужно было знать, в каком порядке вам нужно отсортировать список. Таким образом, интерфейс изолировал две группы программистов, позволяя им разрабатывать свои части программного обеспечения в изоляции. Вот почему во многих языках программирования вы найдете хорошо реализованные и протестированные методы сортировки в api, даже если программисты этих методов не могли знать всех типов объектов и порядков, которые люди хотят сортировать в дальнейшем.

7
ответ дан 24 November 2019 в 16:44
поделиться

Объясняя интерфейсы и объектно-ориентированные концепции в целом непрограммистам, я всегда использую аналогию с домашней развлекательной системой.

DVD-плеер, телевизор, кабельный бокс, пульт дистанционного управления - все это объекты, в которых заключена сложная и изощренная функциональность. Однако они имеют интерфейсы друг к другу и к людям, которые ими управляют, которые в значительной степени скрывают львиную долю этой сложности.

Видеоразъем телевизора - это интерфейс, который реализуется DVD-плеером, кабельным телевизором и рядом других типов устройств.

Я подозреваю, что для студента было бы возможным и, возможно, образовательным упражнением описать свою собственную домашнюю развлекательную систему полностью с помощью кода Java.

29
ответ дан 24 November 2019 в 16:44
поделиться

Я всегда думаю об этом как о способе (устно) общаться как можно меньше, потому что это (хорошее общение) - самая сложная вещь в разработке программного обеспечения. То же самое для веб-служб и SOA. Если вы дадите кому-нибудь интерфейс и скажете: «Пожалуйста, предоставьте мне эту услугу». это очень удобный способ, потому что вам не нужно много объяснять, и компилятор будет проверять, правильно ли они выполнили свою работу вместо вас! (Я имею в виду, не совсем, но, по крайней мере, это обеспечит наличие методов).

0
ответ дан 24 November 2019 в 16:44
поделиться

Я думаю, что в целом практическое обучение всегда помогает укрепить концепции после лекций и примеров. Итак, в том же ключе, что предлагает Меритон, я бы представил две версии одной и той же программы. (хороший пример - быстрая сортировка)

Попросите учащихся несколько раз изменить каждую программу, выявить в программе небольшие ошибки, которые они должны исправить. Я думаю, ваши ученики скоро обнаружат, что интерфейсы предоставляют много преимуществ при разработке программы, когда им придется изменять ее позже!

0
ответ дан 24 November 2019 в 16:44
поделиться

Я бы сказал им: «Интерфейсы определяют , какое поведение предоставляется» и «Реализации обеспечивают это поведение». Часть кода, использующая интерфейс, не нуждается в деталях того, как что-то происходит, ему нужно только знать , что что-то может произойти.

Хорошим примером является шаблон DAO. Он определяет поведение типа «сохранить», «загрузить», «удалить». У вас может быть реализация, которая работает с БД, и реализация, которая работает с файловой системой.

Я думаю, что многие другие ответы пока слишком сложны для студентов, которые не понимают их сразу ...

0
ответ дан 24 November 2019 в 16:44
поделиться

В этом предыдущем вопросе есть несколько хороших сценариев, объясняющих причины использования интерфейсов.

Вопрос о переполнении стека

0
ответ дан 24 November 2019 в 16:44
поделиться

Контракты - это первое, чему учат интерфейсы, но они построены на языке, чтобы обеспечить навыки множественного наследования и избежать сложности множественного наследования .. Так что вы можете научить их, что интерфейсы добавляют поведение во время выполнения программ, или вы можете сказать студентам, что интерфейсы могут использоваться для изменения поведения объектов во время выполнения ..

0
ответ дан 24 November 2019 в 16:44
поделиться

Во-первых, ученики должны усвоить понятие абстракции. Когда вы (вы == ученики) видите учителя, вы можете описать его как учителя ... Вы также можете охарактеризовать его как служащего (школы). И вы можете описать его как человека. Трижды ты будешь прав. Это «титулы», которые вы можете ему дать.

Он учитель, учитель информатики, точно так же, как учитель математики является учителем. Они находятся на одном уровне абстракции. Теперь учитель - это служащий, так же как дворник - служащий. Они находятся на одном уровне абстракции.Работник - это человек, так же как безработный - это человек. Они находятся на одном уровне абстракции.

(Нарисуйте все это на доске в стиле UML).

И это архитектура, которая описывает (примерно) положение учителя естественных наук в обществе.

Теперь уровни абстракции определяют, что общего у общей группы объектов: все учителя учат своих учеников и создают невыполнимые экзаменационные вопросы, чтобы убедиться, что они не сдадут экзамен. В школе работают все сотрудники школы.

В программировании интерфейс - это уровень абстракции. Он описывает действия, которые может выполнять группа объектов. У каждого объекта есть уникальный способ выполнения действия, но тип действия тот же.

Возьмем, к примеру, несколько музыкальных инструментов: пианино, гитару и флейту. Что у них общего ? Их может сыграть музыкант. Вы не можете попросить музыканта подуть на трех инструментах, но можете попросить его сыграть на них.

Архитектура всей концепции будет следующей:

Интерфейс (что у них общего) - это Инструмент. Потому что все они инструменты: это общая абстракция. Что они могут сделать вместе? Играть в. Итак, вы определяете абстрактный метод под названием Play.

Теперь вы не можете определить, как будет играть «Инструмент», потому что это зависит от типа инструмента. Флейта - это разновидность инструмента. Итак, класс Flute реализует инструмент. Теперь вы должны определить, что будет делать музыкант, играя на этом типе инструментов. Итак, вы определяете метод игры. Это определение переопределит определение инструмента.Проделайте то же самое с двумя другими инструментами.

Теперь, если у вас есть список инструментов, но вы не знаете, какого они типа, вы все равно можете «попросить» их сыграть. Каждая флейта будет взорвана. Каждая гитара будет поцарапана. Каждое фортепиано будет ... а ... пианино? что бы ни !

Но каждый объект будет знать, что делать, чтобы выполнить действие «Играть». Вы не знаете, что это за инструменты, но поскольку вы знаете, что это инструменты, вы просите их играть, и они знают, как это делать.

0
ответ дан 24 November 2019 в 16:44
поделиться

Если класс должен обрабатывать ровно одну часть абстрактной функциональности, а не нужно наследовать какой-либо другой класс , можно использовать абстрактный класс для раскрытия функциональности и затем извлеките из этого реальный класс. Однако обратите внимание на два пункта, выделенные курсивом. Интерфейсы позволяют классу вести себя как несколько независимых типов абстрактных вещей, даже если класс является производным от другого класса, который не ведет себя как объекты этих типов. Таким образом, интерфейсы удовлетворяют одному из основных вариантов использования множественного наследования без неприятностей, которые сопровождают множественное наследование.

Простой реальный пример очень практичного интерфейса: iEnumerable. Если в классе содержится произвольное количество элементов определенного типа, очень полезно, чтобы другой класс действовал на все эти элементы, не беспокоясь о деталях объекта, который их содержит. Если бы enumerableThing был абстрактным классом, было бы невозможно, чтобы объект любого класса, производный от чего-то, не являющегося enumerableThing, был передан коду, который ожидал enumerableThing. Поскольку любой класс, включая производные классы, может реализовать enumerableThing независимо от того, делают ли это базовые классы, можно добавить возможность перечисления к любому классу.

0
ответ дан 24 November 2019 в 16:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: