Objaśnianie interfejsów uczniom [zamknięty]

Przez kilka lat byłam asystentką dydaktyczną dla modułu wprowadzenie do programowania - Java dla studentów pierwszego roku.

W większości poszło dobrze i udało nam się dość dobrze przekazać uczniom programowanie zorientowane obiektowo, ale jedno, co uczniowie rzadko widzieli, to Interfejsy.

Praktycznie każde Wyjaśnienie, które podaliśmy, okazało się zbyt wymyślne, aby było przydatne do nauki, lub zbyt oddalone od pozycji początkujących. The reaction we / align = "left" / .. widzisz, "tłumaczone jako" nie Rozumiem i nie brzmią użytecznie".

Ktoś tu ma sposób na skuteczne nauczanie uczniów o interfejsach? Nie jestem już asystentką, ale zawsze mnie to dręczy.

Author: Will, 2010-07-28

26 answers

Jeśli próbujesz wyjaśnić to początkującym, trzymałbym się idei, że interfejsy mogą promować ponowne użycie kodu i modułowość w kodzie:

Na przykład powiedzmy, że będziemy malować niektóre obiekty:

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

Teraz możesz wyjaśnić uczniom, że bez interfejsu Paintable obiekt Painter musiałby mieć metody do malowania pewnych typów obiektów, jak Metoda o nazwie paintFences() i paintRocks() i musielibyśmy mieć nową Collection dla każdego typu obiektów, które chcemy malarz, aby móc malować.

Ale na szczęście mamy interfejsy, które sprawiają, że malowanie obiektów jest proste, a sposób malowania obiektów pozostaje całkowicie do klas, które implementują interfejs do malowania.

EDIT

Kolejną korzyścią, o której zapomniałem wspomnieć, jest to, że jeśli kiedykolwiek będziesz potrzebował dodać nowy obiekt do paint do swojej bazy kodu, wszystko, co musisz zrobić, to stworzyć nową klasę, która implementuje Paintable i klasa Painter nigdy nie musi się zmieniać. W tym sensie Klasa malarza nigdy nie jest zależna od przedmiotów, które zamierza namalować, musi tylko umieć je malować.

EDIT 2

James Raybould przypomniał mi o kluczowym wykorzystaniu interfejsów, o których zapomniałem wspomnieć: posiadanie interfejsu między twoimi komponentami, jak obiekty do malowania i obiekty do malowania, pozwala łatwiej rozwijać się z innymi ludźmi. Jeden programista może pracować na obiektach malarskich, a drugi może pracować na obiektach malarskich i wszystko, co musi zrobić, aby funkcja poprawnie razem jest zdefiniowanie wspólnego interfejsu wcześniej, że będą one zarówno używać. Wiem, kiedy pracowałem nad projektami z innymi ludźmi w projektach na poziomie college ' u, jest to naprawdę pomocne, gdy próbujesz, aby wszyscy pracowali nad różnymi częściami projektu i nadal mają wszystkie komponenty ładnie się ze sobą w końcu.

 31
Author: Ian Dallas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-29 13:15:02

W wyjaśnianiu interfejsów i pojęć zorientowanych obiektowo w ogóle nie-programistom, zawsze używam analogii do systemu domowej rozrywki.

Odtwarzacz DVD, telewizor, Skrzynka kablowa, Pilot Zdalnego Sterowania to obiekty, które zawierają skomplikowaną i wyrafinowaną funkcjonalność. Jednak mają interfejsy do siebie i do ludzi, którzy je obsługują, które w dużej mierze ukrywają lwią część tej złożoności.

Video IN jack telewizora jest interfejsem, który jest realizowany przez DVD odtwarzacz i skrzynka kablowa oraz wiele innych typów urządzeń.

Podejrzewam, że byłoby możliwe i być może ćwiczenie edukacyjne dla ucznia opisanie własnego domowego systemu rozrywki całkowicie za pomocą kodu Java.

 27
Author: aepryus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 18:04:43

" gdzie klasy są czymś, zazwyczaj interfejsy coś robią. Więc mogę mieć samochód, ale nigdy nie pójdę "carring", ale mogę jechać... więc mój samochód może zaimplementować interfejs" drivable"."

EDIT:

Mark ma rację. Interfejsy w ogóle nic nie robią, ale zamiast tego definiują, jakie zachowania się dzieją. I, on również przywołuje dobry punkt o tym, że nie chce zmylić publiczność. Nie, że to jest w porządku, aby mylić doświadczonych deweloperów, ale to na pewno nie jest dobry pomysł na zmylenie nowiutkiej studentki. W związku z tym, zmieniam mój jeden-liniowy na wiele-liniowy.

" gdzie klasy definiują istnienie, interfejsy definiują zachowanie. Klasy definiują, czym coś jest, podczas gdy interfejsy definiują, co coś robi. Więc może mam samochód, i ma takie rzeczy jak silnik, ile ma gazu, co to jest zabytkowe MPG i tym podobne, ale nigdy bym nie poszedł "carring". Z drugiej strony, mogę jechać samochodem... czy mój samochód może prowadzić? Może, jeśli Dam mu metodę jazdy. Mogę również mieć interfejs" Driveable " z metodą jazdy i pozostawić go do samochodu, aby określić, co tak naprawdę oznacza Jazda. Jeśli mam tylko samochody to nic wielkiego mieć interfejs. A co z ciężarówkami? Jeśli oba są do jazdy, mogę po prostu mieć List<Drivable dla obu z nich. Oczywiście spostrzegawczy student mówi: "Dlaczego samochód i ciężarówka nie mogą po prostu rozszerzyć pojazdu, z abstrakcyjną metodą jazdy?"Co właściwie jest bardzo słusznym pojęciem. Ale co z wahadłowcem? Bardzo niewielu z komponenty między samochodem a ciężarówką odnoszą się do promu kosmicznego, więc nie wydaje się dobrze nadawać się do rozszerzenia klasy pojazdu. A co z przyszłymi samochodami? Nie mamy pojęcia, jakie mogą być, mogą nie mieć chasysów, mogą być tylko bąbelkami energii, które poruszają nas, ale nadal możemy nazwać ich zachowanie drive()."

oddechy

Teraz ten paragraf / esej jest trochę gadatliwy, ale widzę, że z kilkoma slajd ' ami lub tablicą, jest skuteczny na pierwszy studenci roku, aby uzyskać ich głowy wokół (zakładając, że rozumieją abstrakcyjne klasy pierwszy i tak).

 16
Author: corsiKa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 18:02:00

Cóż, właśnie wyjaśniłem interfejsy partnerce z pracy, ona uczy się Javy od postępu i naprawdę nie dostała wszystkich rzeczy OOP na początku, więc wyjaśniłem wszystko z punktu widzenia inżynierii oprogramowania, moje wyjaśnienie dla interfejsów, gdzie coś takiego: {]}

Załóżmy, że chcesz zatrudnić hydraulika, aby naprawić niektóre rzeczy w domu, nie wiesz (i nie obchodzi cię wiele), kogo możesz zatrudnić, ale wiesz, co hydraulik musi być w stanie zrobić. Więc ty zdefiniuj zestaw zadań, które każdy, kto twierdzi, że jest hydraulikiem, musi wiedzieć, jak to zrobić. Oczywiście każdy może mieć swój własny sposób wykonywania każdego zadania, ale w końcu osoba, którą zatrudniasz, jest hydraulikiem, ponieważ wie, jak wykonać każde zadanie. Jeśli więc napiszesz to w Javie, pierwszą rzeczą do zrobienia byłoby zdefiniowanie interface hydraulika w taki sposób:

public interface Plumber
{ //silly code here }

Ok, powiedzmy, że wiem, jak wykonać każde zadanie, o które prosisz, więc jestem w pełni zgodny z Twoimi wymaganiami więc według ciebie jestem hydraulikiem. Więc dzisiaj ja decyduję się być twoim hydraulikiem ,a Ty decydujesz się mnie zatrudnić (yay!), na podstawie ostatniego przykładu można powiedzieć, że jestem osobą, która wie, jak rozwijać oprogramowanie i hydraulikę w określony sposób, gdybym miał napisać kod dla mnie jako klasy mógłbym napisać coś takiego: {]}

public class Rick extends Person implements SoftwareDeveloper, Plumber

A później mógłbyś naprawić rzeczy w swoim domu używając mnie jako hydraulika: {]}

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

Od tego momentu Pozostałe pojęcia OOP były łatwe do wyjaśnienia.

 10
Author: Harima555,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-25 17:46:01

Cóż, niedawno, zdarzyło mi się wyjaśnić to komuś bliskiemu. W ten sposób wyjaśniłem pytanie " dlaczego Interfejsy?", jest biorąc przykład z portu USB i dysków USB.

Port USB może być uznany za specyfikację, a każdy dysk USB może się do niego zmieścić, pod warunkiem, że implementuje specyfikację. Tak więc w tym przypadku port staje się interfejsem, a liczne typy dostępnych pamięci USB stają się klasą. Niosąc ten przykład do przodu, gdybym miał dostarczyć komuś USB drive (class), nie musiałbym im mówić (metoda wywołująca), co przechodzę. Gdyby metoda wywołania wzięła dysk USB (typ klasy) jako odniesienie, nie byłbym w stanie przekazać żadnego, ale tylko dysk USB, do którego przeznaczony jest port.

Podsumowując, Intefaces pomaga kompilatorowi w kompilacji z metodą wywołującą (w przypadku użycia, gdy metoda wywołująca oczekuje wystąpienia określonego typu), niezależnie od tego, jaką instancję przekazujesz, zarówno wywołującego, jak i wywołującego. callee są pewni, że to (instancja) zmieści się w referencji interfejsu (port USB dla analogii).

 8
Author: PaiS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 17:25:51

Klasa, spędziliśmy ostatnie kilka sesji implementując quicksort. Trudno było posortować listę osób po nazwisku. Co byś teraz zrobił, gdybyś musiał posortować tę listę według ocen? A co byś zrobił, gdybyś musiał posortować listę dinozaurów według wieku? Jedynym sposobem, jaki znasz do tej pory, jest skopiowanie kodu quicksortu i zmiana porównania i typów, na których działa. To zadziała - dopóki nie znajdziesz tego nieuchwytnego błędu, który zawsze nękał Twój quicksort i musiał go naprawić w kilku tuzin kopii tego quicksortu rozrzuconych po całym miejscu.

Dzisiaj nauczymy się lepszego sposobu.

Możemy napisać quicksort bez definiowania kolejności, w którą chcemy posortować listę, i zdefiniować tę kolejność (i tylko tę kolejność) oddzielnie, gdy wywołujemy ten quicksort.

[ Wstaw Wyjaśnienie mechaniki interfejsów i polimorfizmu, używając interfejsu komparatora jako przykładu, tutaj]

Teraz jest tylko jedna kopia quicksortu, a błędy tylko trzeba to naprawić raz. Ponadto, ludzie mogą używać quicksort bez zrozumienia go (lub jeśli zrozumieli go, bez myślenia o jego mechanice, gdy chcesz coś posortować). Ponadto osoby piszące quicksort nie musiały znać kolejności, jakiej potrzebujesz, aby posortować swoją listę. Tak więc interfejs wyizolował dwie grupy programistów, pozwalając im rozwijać swoje części oprogramowania w izolacji. Dlatego w wielu językach programowania znajdziesz dobrze zaimplementowany i przetestowany sort metody w api, mimo że programiści tych metod nie mogli znać wszystkich typów obiektów i rozkazów, które ludzie chcą później sortować.

 7
Author: meriton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 21:04:09

Zwykle używam "umowy", ale" obietnice uroczystego dostarczenia " mogą również pomóc w zrozumieniu.

 6
Author: Thorbjørn Ravn Andersen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 19:33:15

Polecam pierwszy rozdział Head First Design Pattern s do tego. Symulacja kaczki wyjaśnia problem z używaniem dziedziczenia, a reszta rozdziału wyjaśnia, jak to zrobić.

 5
Author: JRL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 18:07:51

To wyjaśnia najlepiej : (odwołuje się z tego tutorial)

Istnieje wiele sytuacji w inżynierii oprogramowania, kiedy ważne jest, aby różne grupy programistów zgodziły się na "kontrakt", który określa, w jaki sposób ich oprogramowanie współdziała. Każda grupa powinna być w stanie napisać swój kod bez żadnej wiedzy o tym, jak kod drugiej grupy jest napisany. Ogólnie rzecz biorąc, interfejsy są takimi umowami. Na przykład wyobraźmy sobie Futurystyczne społeczeństwo, w którym sterowane komputerowo zrobotyzowane samochody przewożą pasażerów ulicami miasta bez ludzkiego operatora. Producenci samochodów piszą oprogramowanie (oczywiście Java), które obsługuje samochód-zatrzymaj, Uruchom, Przyspiesz, skręć w lewo i tak dalej. Inna grupa przemysłowa, producenci elektronicznych przyrządów naprowadzających, tworzy systemy komputerowe, które odbierają dane o pozycji GPS (Global Positioning System) i bezprzewodową transmisję warunków drogowych i wykorzystują te informacje do prowadzenia samochodu.

Producenci samochodów musi opublikować standardowy interfejs branżowy, który szczegółowo określa, jakie metody można wywoływać, aby samochód poruszał się (dowolny samochód, od dowolnego producenta). Producenci wskazówek mogą następnie napisać oprogramowanie, które wywołuje metody opisane w interfejsie, aby sterować samochodem. Żadna grupa przemysłowa nie musi wiedzieć, w jaki sposób oprogramowanie drugiej grupy jest wdrażane. W rzeczywistości każda grupa uważa swoje oprogramowanie za wysoce zastrzeżone i zastrzega sobie prawo do modyfikowania go w dowolnym momencie, tak długo, jak będzie to kontynuowane aby stosować się do opublikowanego interfejsu.

Więcej linku: http://download-llnw.oracle.com/javase/tutorial/java/concepts/interface.html

 3
Author: YoK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 17:17:02

Zrozumienie interfejsów nie różni się zbytnio od zrozumienia polimorfizmu i zależności IS-A. Wszystkie klasy implementujące ten sam interfejs mogą być jednakowo manipulowane przez program jako typ "base" ze względu na relacje ustanowione przez implementację interfejsu lub dziedziczenie klasy bazowej.

Wybór pomiędzy interfejsem a klasą bazową jest decyzją projektową. To byłoby proste.

  • Zdefiniuj klasę, gdy twoja implementacja może przyjąć pełną lub częściowe zachowanie klasy.
  • uczyń tę klasę abstrakcyjną, aby wskazać, że klasa bazowa nie jest kompletną implementacją i nie może być używana tak, jak jest.
  • zapewnienie interfejsu zamiast klasy bazowej, jeśli nie ma sensu dostarczanie częściowej implementacji.

Korzyści z interfejsów i dziedziczenia są prawie takie same. Interfejs jest po prostu bardziej abstrakcyjną definicją typu niż klasa bazowa.

Update

Oto prosty program, którego możesz użyć do zademonstrowania, jak podobne są dziedziczenia i interfejsy. Zmodyfikuj program, aby Base stał się interfejsem zamiast klasą. W ClassA, zamień "extends" na "implements". Wynik programu będzie taki sam.

Celem ClassB jest dalsze zilustrowanie znaczenia relacji między klasą a jej interfejsem/klasą bazową. Instancja ClassB może nie zostać przekazana do processBase pomimo podobieństw do Base, chyba że ustalimy wyraźny związek.

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
Author: Philippe A.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 19:44:30

Projektowanie zorientowane na interfejs opisuje to lepiej niż kiedykolwiek mogłem http://pragprog.com/titles/kpiod/interface-oriented-design . autor wykorzystuje kilka doskonałych przykładów interfejsów a dziedziczenie dla rzeczy takich jak Taksonomia królestwa zwierząt. Ma jedne z najlepszych argumentów przeciwko nadmiernemu dziedziczeniu i rozsądnemu korzystaniu z interfejsów, jakie czytałem do tej pory.

Banda stron z niezgodnymi sposobami ich wychowywania:

Spis z Facebook.java :

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

Lista YouTube.java :

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

Lista StackOverflow.java :

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

Klient ręcznie obsługujący różne metody, których strony internetowe używają, aby przynieść się:

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

Wprowadzenie interfejsu strony internetowej, aby ułatwić pracę Klienta:

Spis strony internetowej.java :

public interface Website {
    void showWebsite();
}

Lista [[21]} Facebook.java :

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

Lista YouTube.java :

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

Lista StackOverflow.java :

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

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

Whoop-de-doo, więcej kodu za nic? Właściwie możemy pójść trochę dalej i niech klient połączy kilku przyjaciół, aby pomogli mu znaleźć i renderować strona internetowa:

Lista 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]));
    }
}

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

Spis stron internetowych .java :

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

Patrząc wstecz na ClientWithoutInterface , jest on całkowicie połączony zarówno z konkretnym wyszukiwaniem, jak i renderowaniem. Byłoby to bardzo trudne do zarządzania, gdy dojdziesz do setek lub tysięcy witryn. Z strona internetowa interfejs w miejscu WebsiteFinder może łatwo być przekonwertowane do kopii zapasowej na mapie, bazie danych lub nawet wyszukiwarce internetowej, aby zaspokoić rosnącą skalę.

Interfejsy umożliwiają oddzielenie roli od komponentu, który ją realizuje. Pozwalają one na zamianę alternatywnych rozwiązań tego samego problemu w oparciu o praktycznie wszystko: {]}

  • Obciążenie prądowe maszyny

  • Rozmiar zbioru danych (można wybrać algorytmy sortowania)

  • Użytkownik wnioskujący o działanie jest wykonywane

 2
Author: Alain O'Dea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-29 01:25:19

Pisałem to jako komentarz do odpowiedzi Harima555s, ale się rozszerzyło. Zastanawiałem się, czy bardziej sensowne jest zaczynanie od drugiego końca - dać im odczuć, jak interfejsy są przydatne, zanim przejdziemy do tego, jak je piszesz.

Zakładając, że mają dobre pojęcie o dziedziczeniu, polimorfizmie i klasach abstrakcyjnych. Prawdopodobnie zacznę od podsumowania zajęć abstrakcyjnych, prosząc jednego z uczniów o wyjaśnienie ich.

Następnie przedstaw przykład klas z interfejsami, aby uzyskać nad pojęciem ról / kontraktów. Aby uprościć sprawy, zacznij od pojedynczej klasy wyższej.

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

Nie Tłumacz tego za dużo, ale spróbuj przekonać ucznia, co może oznaczać składnia-być może pokazanie kodu, który odwołuje się do hydraulika lub programisty.

Zapytaj ich, jak osiągną to samo, korzystając z dziedziczenia od osoby. Powinny one utknąć dość szybko, lub wymyślić wiele dziedziczenia. Aby uniknąć dyskusji o problemie diamentów do później powiedzmy, że nie ma nakładających się metod w rolach.

Następnie spróbowałbym przeboleć pomysł, że ten sam interfejs może być używany na różnych typach klas.

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

Ponownie spróbuj skłonić ich do zastanowienia się, w jaki sposób mogliby zaimplementować to samo, używając wspólnej klasy nadrzędnej i nadrzędnej.

Następnie zilustruj, jak piszesz kod polimorficzny za pomocą interfejsu, a nie Klasy - powiedzmy TravelAgent, który sprzedaje bilety na pasażera. / Align = "left" / - że można pisać kod polimorficzny, który działa na klasach z różnych hierarchii.

W tym momencie, prawdopodobnie powinni być pod złudzeniem, że interfejs jest prawie jak możliwość dodania kolejnej superklasy do klasy i będą mogli uchwycić zalety wielokrotnego dziedziczenia.

Więc teraz musimy wyjaśnić, dlaczego to komplikuje sprawy, a Interfejsy nie mają domyślnej implementacji, poprzez zrozumienie problemu diamond.

Wróć do pierwszego przykład: spraw, aby pracowali nad tym, co się stanie, jeśli SoftwareDeveloper i Hydraulik mają metodę "MakeDrink" (jeden robi Colę, drugi robi kawę) i wykonamy MakeDrink na Ricku.

Spróbuj nakłonić kogoś do rozważenia idei, że jeśli MakeDrink jest utrzymywany w abstrakcji w obu "superklasach", problem zniknie. W tym momencie, mając stronę koncepcyjną, powinniśmy być gotowi do omówienia składni do definiowania interfejsu.

(rozważałem wprowadzenie drugiego powodu - trudności w pisaniu kodu generycznego, który mógłby być zastosowany do różnych hierarchii klas, ale okazało się, że kończysz z "cóż, dlaczego nie możesz dziedziczyć atrybutu altitude z interfejsu" lub dyskutując o programowaniu generycznym zbyt wcześnie).

Myślę, że do tej pory powinniśmy byli opisać te pojęcia za pomocą przykładów Myszki Miki - a następnie można było wrócić do wyjaśnienia poprawnej terminologii technicznej i użyć rzeczywistych przykładów z API Java.

  • I wouldn ' t chcesz zdezorientować ludzi, gdy próbują uczyć się Java / interfejsów, ale kiedy już to opanują, warto zwrócić uwagę, że inne języki OO przyjmują różne podejścia do tego samego problemu, od wielokrotnego dziedziczenia po pisanie kaczek - i jeśli są zainteresowani, powinni je zbadać.
 2
Author: JulesLt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-29 10:59:57

Uczysz też JDBC? Weź to jako przykład. To doskonały przykład na to, jak potężne są interfejsy w świecie rzeczywistym. W JDBC piszesz kod przeciwko API, które istnieje prawie tylko interfejsy. Sterownik JDBC jest konkretną realizacją. Możesz łatwo ponownie użyć kodu JDBC na wielu bazach danych bez przepisywania kodu. Wystarczy przełączyć plik JAR implementacji sterownika JDBC i nazwę klasy sterownika, aby działał na innym DB.

Przynajmniej korzystanie z interfejsów oferuje masz możliwość zmiany od konkretnej implementacji (logiki kodu, która jest odpowiedzialna za zachowanie) w jakiś sposób/punkt bez przepisywania całego kodu. Staraj się używać przykładów z prawdziwego świata przy wyjaśnianiu rzeczy. To by miało więcej sensu.

 1
Author: BalusC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 17:47:42

Cóż, znalazłem ostatnio bardzo przydatną metodę korzystania z interfejsu.

Mamy wiele obiektów...

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

Teraz ktoś tworzy (tzn.) tabelę i chce pokazać niektóre obiekty z listy wszystkich obiektów, ale aby pokazać obiekty na liście musi napisać metodę, która zwraca łańcuch [].

String[] toArrayString()

Więc implementuje tę metodę we wszystkich klasach, które musi w tabeli

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

Teraz, kiedy tworzy tabelę, pisze smth w ten sposób

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

Z interfejsem kod ten może być znacznie krótszy i łatwiejszy do odczytania i utrzymania:

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

Ponadto, możemy zaimplementować wiele interfejsów w bardzo czysty i skuteczny sposób bez żadnych pochodnych (wyprowadzenie jest czasami niemożliwe i nie tylko w przypadku, gdy Klasa używa już jakiegoś innego rodzaju pochodnych).

 1
Author: Grzegorz Gajos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 20:18:17

Interfejsy zapewniają spojrzenie na to, co klasa musi zrobić na przykład możesz mieć interfejs zwierzęcy i powiedzmy, że ma metodę zwaną speak (), cóż każde zwierzę może mówić, ale wszystkie robią to inaczej, ale to pozwala Ci rzucić wszystko, co implementuje zwierzę do zwierzęcia, więc możesz mieć listę zwierząt i sprawić, że wszystkie będą mówić, ale użyją własnej implementacji. Interfejsy są po prostu opakowaniami dla tego rodzaju rzeczy.

 0
Author: Jesus Ramos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 17:09:42

W tym poprzednim pytaniu jest kilka dobrych scenariuszy, które wyjaśniają, dlaczego za używaniem interfejsów.

Pytanie O Przepełnienie Stosu

 0
Author: Antonio Louro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:10

Rzeczywista wartość interfejsów wynika z możliwości nadpisania komponentów w interfejsach API lub frameworkach innych firm. Chciałbym skonstruować zadanie, w którym uczniowie muszą nadpisać funkcjonalność w wstępnie zbudowanej bibliotece, której nie mogą zmienić(i nie mają źródła).

Aby być bardziej konkretnym, Załóżmy, że masz "framework", który generuje stronę HTML zaimplementowaną jako klasa strony. I page.render (stream) generuje html. Załóżmy, że strona bierze przykład z sealed ButtonTemplate class. Obiekt ButtonTemplate posiada własną metodę renderowania tak, że w zakładce.render (stream) buttonTemplate.render (label, stream)jest wywoływany wszędzie tam, gdzie jest przycisk i tworzy html dla przycisku Wyślij. Jako przykład dla uczniów, powiedzmy, że chcemy zastąpić te przyciski submit linkami.

Nie dałbym im innego kierunku niż opisanie ostatecznego wyniku. Będą musieli bić się po głowach próbując różnych rozwiązań. " czy powinniśmy spróbować przetworzyć znaczniki przycisków i zastąpić znacznikami kotwicy? Czy możemy podklasować ButtonTemplate, aby robić to, co chcemy? Czekaj. Zamknięte! Co oni sobie myśleli, kiedy zapieczętowali tę klasę!?!" następnie po tym przypisaniu Pokaż drugi framework z interfejsem ILabeledTemplate z metodą render (label,stream).

 0
Author: SargeATM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 17:35:12

Oprócz innych odpowiedzi, możesz spróbować wyjaśnić to z innej perspektywy. Studenci na pewno już wiedzą o dziedziczeniu, bo jest on wepchnięty do gardeł każdego ucznia Javy z prawdopodobnie pierwszego wykładu. Czy słyszeli o wielokrotnym dziedziczeniu? Rozwiązanie metody było postrzegane jako problem projektowy w C++ (a także w Perlu i innych językach wielokrotnego dziedziczenia), ponieważ koncepcyjnie jest niejednoznaczne co dokładnie powinno się zdarzyć, gdy metoda jest wywoływana w podklasa, która jest zdefiniowana w dwóch klasach bazowych. Obaj zostali straceni? Która pierwsza? Czy można się konkretnie do nich odnieść? Zobacz też problem diamentowy . Rozumiem, że to zamieszanie zostało rozwiązane po prostu przez wprowadzenie interfejsów, które nie mają implementacji, więc nie ma dwuznaczności co do tego, którą implementację użyć podczas rozwiązywania metod.

 0
Author: Hut8,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 17:42:20

Jeśli klasa musi obsługiwać dokładnie jeden fragment abstrakcyjnej funkcjonalności, a nie musi dziedziczyć żadnej innej klasy , można użyć klasy abstrakcyjnej, aby ujawnić funkcjonalność, a następnie wyprowadzić z niej prawdziwą klasę. Zwróć jednak uwagę na dwie pozycje kursywą. Interfejsy umożliwiają zachowanie klasy jako kilku niezależnych typów abstrakcyjnych rzeczy, nawet jeśli klasa pochodzi z innej klasy, która nie zachowuje się jak te typy rzeczy. Tak więc, interfejsy spełniają jeden z głównych przypadków użycia dziedziczenia wielokrotnego, bez zawirowań, które towarzyszą dziedziczeniu wielokrotnemu.

Prosty przykład praktycznego interfejsu: iEnumerable. Jeśli klasa posiada pewną dowolną liczbę pewnego rodzaju elementów, jest bardzo przydatne dla innej klasy, aby działała na wszystkich tych elementach bez martwienia się o szczegóły obiektu, który je przechowuje. Gdyby "wyliczenie" było klasą abstrakcyjną, byłoby niemożliwe dla obiekt dowolnej klasy, który wywodził się z czegoś, co nie było" enumerableThing " do przekazania do kodu, który oczekiwał enumerableThing. Ponieważ każda klasa, łącznie z klasami pochodnymi, może zaimplementować wyliczenie bez względu na to, czy klasy bazowe to robią, możliwe jest dodanie możliwości wyliczenia do dowolnej klasy.

 0
Author: supercat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 17:55:49

Dawno temu czytałem książkę (nie pamiętam jej nazwy) i miała całkiem dobrą analogię do interfejsów. Jeśli ty (lub Twoi uczniowie) kiedykolwiek poszedłeś do lodziarni Cold Stone Creamery, zabrzmi to znajomo. Cold Stone ma lody i z lodami można dodać kilka różnych rzeczy do lodów (zwanych mieszanek w Cold Stone). Te miksy byłyby analogiczne do interfejsów. Twoja klasa (lub lody) może mieć tyle interfejsów (lub mieszanek), ile ty chcę. Dodanie interfejsu (lub mieszania) doda zawartość (lub smak) tego interfejsu (lub mieszania) do twojej klasy (lub lodów). Mam nadzieję, że to pomoże!

 0
Author: Icemanind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 19:40:00

Kontrakty są pierwszymi rzeczami, które są nauczane o interfejsach, ale są zbudowane w języku, aby zapewnić umiejętności wielokrotnego dziedziczenia i uniknąć złożoności dziedziczenia wielokrotnego.. Możesz więc nauczyć ich, że interfejsy dodają zachowanie środowiska wykonawczego do programów lub powiedzieć uczniom, że interfejsy mogą być używane do zmiany zachowania obiektów..

 0
Author: LostMohican,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 19:47:51

Najpierw uczniowie muszą zrozumieć pojęcie abstrakcji. Kiedy ty (ty = = uczniowie) widzisz nauczyciela, możesz opisać go jako nauczyciela... Można go również opisać jako pracownika szkoły. I możesz opisać go jako osobę. Będziesz miał rację trzy razy. To są "tytuły", które możesz mu dać.

On jest nauczycielem, nauczycielem informatyki, tak jak nauczyciel matematyki jest nauczycielem. Są na tym samym poziomie abstrakcji. Teraz nauczyciel jest pracownikiem, w tak jak Woźny jest pracownikiem. Są na tym samym poziomie abstrakcji. Pracodawca to osoba, tak samo bezrobotny to osoba. Są na tym samym poziomie abstrakcji.

(narysuj całość na planszy w sposób UML).

I to jest architektura, która będzie opisywać (z grubsza) pozycję nauczyciela Nauk Ścisłych w społeczeństwie.

Teraz poziomy abstrakcji definiują to, co łączy wspólną grupę przedmiotów : wszyscy nauczyciele uczą ich uczniów i tworzyć niemożliwe pytania egzaminacyjne, aby upewnić się, że nie. Wszyscy pracownicy szkoły pracują dla szkoły.

W programowaniu interfejs jest poziomem abstrakcji. Opisuje działania, które grupa obiektów może wykonać. Każdy obiekt ma unikalny sposób wykonania akcji, ale typ akcji jest taki sam.

Weźmy na przykład kilka instrumentów muzycznych : fortepian, gitarę i flet. Co ich łączy ? Muzyk może je zagrać. Nie możesz zapytać muzyk dmuchać w 3 instrumenty, ale można go poprosić, aby je odtworzyć.

Architektura całego konceptu będzie następująca:

Interfejs (co mają ze sobą wspólnego) to Instrument. Ponieważ wszystkie one są instrumentami : To abstrakcja, którą wszystkie mają ze sobą wspólnego. Co mogą ze sobą wspólnego ? Graj. Więc definiujesz abstrakcyjną metodę zwaną grą.

Teraz nie możesz określić, jak" Instrument " będzie grał, ponieważ zależy to od rodzaju instrumentu. Flet to rodzaj instrumentu. Tak więc Klasa flet implementuje Instrument. Teraz musisz określić, co muzyk będzie robił, gdy gra na tego typu instrumencie. Więc definiujesz metodę gry. Definicja ta zastąpi definicję instrumentu. Zrób to samo z 2 innymi instrumentami.

Teraz, jeśli masz listę instrumentów, ale nie wiesz, jakiego typu są, nadal możesz "poprosić" je, aby grały. Każdy flet zostanie wysadzony. Każda gitara będzie porysowana. Każdy fortepian będzie ... huh... / align = "left" / nieważne !

Ale każdy obiekt będzie wiedział, co zrobić, aby wykonać akcję "Play". Nie wiesz, jaki to instrument, ale skoro wiesz, że to instrumenty, prosisz ich, aby grali, a oni wiedzą, jak to zrobić.

 0
Author: Philippe Carriere,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 20:04:53

Możesz również porównać i skontrastować interfejsy w Javie z C++ (gdzie kończysz używając wielu klas dziedziczenia i / lub "przyjaciół").

(przynajmniej mi to pokazało jak dużo prostszych / łatwiejszych interfejsów jest w Javie : -)

 0
Author: Eno,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 20:22:07

Powiedziałbym im: "Interfejsy definiują Jakie zachowania są dostarczane"i" implementacje dostarczają te zachowania". Fragment kodu, który używa interfejsu, nie potrzebuje szczegółów Jak {[2] } rzeczy się dzieją, musi tylko wiedzieć co rzeczy mogą się wydarzyć.

Dobrym przykładem jest wzór DAO. Definiuje zachowanie takie jak "save", "load", "delete". Możesz mieć implementację, która działa z DB i implementację, która trafia do systemu plików.

Myślę, że wiele innych odpowiedzi do tej pory są zbyt skomplikowane dla studentów, którzy nie dostać go od razu...

 0
Author: hvgotcodes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 20:37:25

Myślę, że ogólnie rzecz biorąc, praktyczna nauka zawsze pomaga wzmocnić koncepcje po wykładach i przykładach. Tak więc w tym samym duchu, co sugeruje meriton, chciałbym przedstawić dwie wersje tego samego programu. (quicksort jest dobrym przykładem)

Każ uczniom zmodyfikować każdy program kilka razy, ujawnić subtelne błędy w programie, aby mogli je naprawić. Twoi uczniowie wkrótce przekonają się, że interfejsy zapewniają wiele korzyści podczas projektowania programu, gdy to oni muszą go zmodyfikować później!

 0
Author: weiy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 21:29:23

Zawsze uważam to za środek do (werbalnej) komunikacji jak najmniej, ponieważ to (dobra komunikacja) jest najtrudniejszą rzeczą w inżynierii oprogramowania. To samo dotyczy usług internetowych i SOA. Jeśli dasz komuś interfejs i powiesz " proszę, dostarcz mi tę usługę."jest to bardzo wygodny sposób, ponieważ nie musisz wiele wyjaśniać, a kompilator sprawdzi, czy wykonał właściwą pracę, zamiast Ciebie! (Znaczy, nie do końca, ale przynajmniej zapewni to, że metody są tam).

 0
Author: Enno Shioji,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-28 22:36:39