Warum würden Sie deklarieren Sie ein Interface und dann instantiieren ein Objekt mit dem es in Java?
Einen Freund und ich studieren, Java. Wir waren auf der Suche, an den Schnittstellen, die heute und wir haben in ein bisschen eine Diskussion darüber, wie Schnittstellen verwendet werden.
Den Beispiel-code mein Freund mir zeigte, enthalten diese:
IVehicle modeOfTransport1 = new Car();
IVehicle modeOfTransport2 = new Bike();
Wo IVehicle ist ein interface, dass implementiert ist sowohl in der Auto-und Motorrad-Klassen.
Bei der Definition einer Methode, die akzeptiert IVehicle als parameter können Sie die interface-Methoden, und wenn Sie den code ausführen der oben genannten Objekte normal arbeiten. Das funktioniert aber völlig in Ordnung, wenn man erklärt, das Auto und Fahrrad, wie Sie normalerweise würden, wie diese:
Car modeOfTransport1 = new Car();
Bike modeOfTransport2 = new Bike();
So, meine Frage ist - warum würden Sie die frühere Methode, in den letzteren bei der Deklaration und der Instanzierung der modeOfTransport Objekte? Spielt es eine Rolle?
- Was passiert also, wenn Sie wollen, schreiben Sie eine Methode, braucht entweder ein Auto oder ein Fahrrad als parameter? Was nun?
- kannst du die Methoden auf die IVechical-Schnittstelle? Was passiert, wenn Sie behandeln möchten ein neues Objekt Typ ie-Bus oder SpaceRocket
- viele Antworten wurden downvoted. downvoters, Pflege zu erklären, warum?
- eine Menge von den Antworten einfach nicht auf die Frage.
- Stimmen, zu viele downvotes auf vernünftige Antworten!
- Ich erkläre meine downvotes: jeder scheint hier zu starten, in einer Erklärung über Polymorphismus oder der Zweck von interfaces, die ist nicht das, was der OP gefragt. Die OP wurde Sie gefragt, ob Sie sofort gegossen, um ein interface-Typ oder aufzuschieben, das casting, bis später.
- 7 von 10 Antworten erhielt 2 downvotes. Von denen, die haben, die meisten haben die Frage. In jedem Fall würde ich das kaum bezeichnen Sie als nicht sinnvoll (die angegebenen Kriterien für die downvote).
- Nein, das war er nicht. Er wurde gefragt, speziell "warum würden Sie die frühere Methode, in den letzteren". Er hat nicht einmal erwähnt Gießen.
- Ich bin nur unter Angabe der wahrscheinlichen Ursache. (Ich wusste nicht downvote vorhanden.)
- Die OP war nicht gefragt, warum eine Schnittstelle über einen konkreten Typ. Die OP wurde Sie gefragt, "warum definieren Sie die Variablen in dieser Art und Weise statt, dass die Art und Weise", was für mich das gleiche wie zu Fragen, "impliziten cast jetzt, oder später?"
- Ich glaube nicht, dass sich eine logische Schlussfolgerung. Die beiden sind unglaublich Verschieden.
- Was für eine schreckliche Logik Sprung! Schreckliche Grund, downvote. Sie sollten sich schämen.
- Ich bin gespannt, welche Antwort wird akzeptiert! Ich bin damit einverstanden, dass eventuell off-topic, ist kein Grund für eine down-vote, solange die Antwort selbst richtig ist.
- Ich sollte eine Menge Dinge.
- Danke an Alle, die Antworten und die Diskussion hat mir sehr geholfen, ich kenn die richtige ist, basiert Auf der höheren Abstimmung. Abgesehen davon, dass ich nicht entscheiden konnte zwischen Larry Watanabe oder Oscar Gomez Beiträge. Ich bin damit einverstanden, dass einige der Antworten zu haben scheinen, wurde unnötig nach unten gestimmt. Nochmals vielen Dank.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es spielt keine Rolle, es.
Wo es wirklich wichtig ist im anderen Schnittstellen, die die Bedienung auf IVehicle. Wenn Sie akzeptieren, dass die Parameter und Rückgabewerte als IVehicle, dann wird der code leichter erweiterbar.
Wie Sie bemerkt haben, entweder von diesen Objekten übergeben werden kann, um eine Methode, die akzeptiert IVehicle als parameter.
Wenn Sie nachfolgenden code, verwendet Auto oder Motorrad spezifischen Operationen, die verwendet wurden, dann wäre es von Vorteil, zu erklären, wie Auto oder Fahrrad. Die Auto-und Bike-spezifische Operationen zur Verfügung stehen würde, für jeden der relevanten Objekte, und beide würden verwendbar sein (D. H. weitergegeben werden konnten) als IVehicle.
IVehicle
was für ein Typ die variable ist deklariert, wie, wie lange, wie es implementiertIVehicle
. Ich denke, die "beste" Beispiel wirklich zu sehen, die macht der Schnittstellen ist mit dependency injection.modeOfTransport1
undmodeOfTransport2
würde, dann wäre es eine gute Sache, die Sie deklariert Sie als Schnittstelle Instanzen eher als konkrete Instanzen.Es ist ein großes plus auf eine Deklaration über die Schnittstelle, die ist, was ist bekannt als "für eine Schnittstelle Code" statt "Codierung auf eine Implementierung" das ist eine große Object-Oriented Design (
HOCHWASSERSCHUTZ
) Prinzip, auf diese Weise können Sie deklarieren eine Methode wie diese:und diese akzeptieren alle Objekte, die diese Schnittstelle implementiert, dann zur Laufzeit erfolgt ein Aufruf der Umsetzung wie diese:
Antwort auf die ursprüngliche Frage, warum würden Sie einen über den anderen gibt es mehrere Gründe:
1) Deklarieren Sie eine Schnittstelle bedeutet, dass Sie später ersetzen Sie diesen Wert mit anderen konkrete Klasse, die diese Schnittstelle implementiert, statt fest, dass insbesondere konkrete Klasse
2) können Sie den vollen nutzen des Polymorphismus, indem Sie über ein interface, weil jede Implementierung kann der Aufruf der richtigen Methode zur Laufzeit.
3) Folgen Sie der OOD-Prinzip von code, um eine Schnittstelle
IInterface var = new ConcreteClass();
sind, nicht, wie Schnittstellen funktionieren.IInterface
wenn Sie wissen, dass seine konkrete Klasse. Was du gepostet hast funktioniert genau die gleiche Weise in beiden Szenarien der OP ausgesetzt.Du bist wirklich zu Fragen: welche Referenz-Typ sollte ich verwenden?
In der Regel, die Sie verwenden möchten, die als Allgemeine Referenz geben wie möglich, dass noch gibt Ihnen Zugriff auf das Verhalten, das Sie brauchen. Dies bedeutet, dass alle Schnittstellen oder übergeordneten Klassen von Ihrem konkreten Typ, sondern als der konkrete Typ selbst. Natürlich, nehmen Sie nicht dieser Stelle zu weit-zum Beispiel, Sie wollen sicher nicht zu erklären, alles als ein
Object
!Betrachten Sie diese Optionen:
Alle drei sind gültig, aber in der Regel die erste option
values1
ist besser, weil Sie nur in der Lage sein, um Zugriff auf das Verhalten derSet
- Schnittstelle, so dass Sie später tauschen zu können in einer anderen Implementierung ganz einfach:Hüten Sie sich vor der Verwendung der zweiten option
values2
. Es erlaubt Ihnen spezifische Verhalten derTreeSet
Umsetzung in der Weise, dass der Austausch in einer anderen Implementierung vonSet
wird immer schwieriger. Das ist in Ordnung, solange das ist Ihr Ziel. Also, in deinem Beispiel, verwenden Sie eineCar
oderBike
nur als Referenz, wenn Sie benötigen, Zugang zu etwas, das nicht in derIVehicle
- Schnittstelle. Seien Sie sich aber bewusst, dass das folgende nicht funktionieren würde:Dennoch gibt es Zeiten, wenn Sie benötigen Zugriff auf die Methoden, die nicht in den Allgemeinen Typ. Dieser Vorgang wird in der Dritten option
values3
-- die Referenz ist spezifischer alsSet
, die können Sie sich verlassen auf das Verhalten vonSortedSet
später.Die Frage zu Referenztypen gilt nicht nur dort, wo Variablen deklariert sind, aber auch Methoden, bei denen Sie angeben müssen, die den Typ jedes Parameters. Glücklicherweise ist die "Verwendung als Allgemeine Referenz geben wie möglich" Faustregel gilt für die Parameter der Methode zu.
Wenn Sie das Programm um eine Schnittstelle, die Sie code schreiben, der kann jede Art von Fahrzeug. Also in Zukunft deinen code, ohne änderung, sollte die Arbeit mit Züge und Flugzeuge.
Wenn Sie ignorieren die Schnittstelle, dann stecken Sie mit Autos und Fahrräder, und alle neuen Fahrzeuge, benötigen zusätzliche code-änderungen.
Das Prinzip dahinter ist:
Weil Sie nicht wirklich kümmert, was die Umsetzung ist... nur was es ist das Verhalten.
Sagen, Sie haben ein Tier
Nun möchten Sie geben Ihrem Kind ein Haustier.
Und Sie bekommen es später zurück
Würden Sie nicht wollen, zu gehen
Weil Sie nicht wissen, ob das Kind einen Hund hatte oder nicht. Und Sie kümmern sich nicht. Sie weiß nur, dass --Tiere-- reden dürfen. Sie wissen nichts über Ihre Interaktionen mit Möbeln oder Hydranten. Wissen Sie, Tiere sind für das sprechen. Und es macht deine Tochter kichern (oder nicht!)
Mit dabei, wenn Sie einen Goldfisch, der kid ' s Reaktion ziemlich lahm ist (stellt sich heraus, Goldfische nicht sprechen!) Aber wenn Sie einen tragen, die Reaktion ist ziemlich beängstigend!
Und Sie konnte nicht dies tun wenn Sie sagte
weil Sie beschränken sich auf die Fähigkeiten einer Katze.
Ehrlich gesagt ist dein argument eher irrelevant. Was dort geschieht, ist eine implizite Konvertierung in eine
IVehicle
. Sie und Ihr Freund scheint sich darüber zu streiten ob es besser ist, tun Sie es sofort (nach der ersten code-listing), oder später (beim Aufruf der Methode, nach der zweiten code-listing). So oder so, es wird implizit konvertiert werden, um eineIVehicle
, also die eigentliche Frage ist-zu tun, müssen Sie den Umgang mit einem Auto, oder nur ein Fahrzeug? Wenn alles, was Sie brauchen, ist ein IVehicle die erste Art und Weise ist völlig in Ordnung (und besser, wenn Sie zu einem späteren Zeitpunkt wollen transparent swap ein Auto für ein Fahrrad). Wenn Sie brauchen, um es zu behandeln wie ein Auto an anderen Punkten in Ihrem code, dann lass es einfach wie beim Auto.Vehicle
statt einerCar
Sie die Menschen zwingen, zu denken, Dinge in Bezug auf eineVehicle
. Dieser Weg, wenn Sie ersetzen IhreCar
mit einemPlane
, die meisten sicherlich passieren, irgendwann während der Lebensdauer der Anwendung, Sie haben keine (wiederhole, KEIN) refactoring zu tun.Car
ojbects (vielleicht einCarMechanic
Objekt). Modularität und Schnittstellen sind gut, aber Sie müssen noch die Bereitstellung für die Spezialisierung.HashSet
statt einerSet
? Nie. Warum? Denn es war gut gestaltet. Modularität und Schnittstellen sind gut, und die Spezialisierung ist ein Anzeichen für einen primitiven Verständnis des Problems.Schnittstellen deklarieren und instanziieren Sie mit Objekten ermöglicht, die für ein leistungsfähiges Konzept genannt Polymorphismus.
Explizit eine Antwort auf die Frage: würden Sie verwenden eine interface-Deklaration (auch wenn Sie wissen, dass der konkrete Typ), so dass Sie weitergeben können mehrere Arten (, implementieren die gleiche Schnittstelle) an eine Methode oder Sammlung; dann wird das Verhalten gemeinsam jedes der Umsetzung geben kann aufgerufen werden, egal, was der tatsächliche Typ ist.
Car
übergeben werden kann, um eine Methode oder Sammlung nimmt eineIVehicle
. Es gibt keine Anforderung, dass es erklärt werden alsIVehicle
.sowie Schnittstellen sind Verhaltensweisen und Klassen sind Ihre Umsetzung, so daß es mehrere Gelegenheiten später, wenn Sie das Programm, wo Sie nur kennen das Verhalten(interface). und zu nutzen, Sie umzusetzen, Sie zu bekommen davon profitieren. es ist im Grunde verwendet, um zu verbergen Implementierungsdetails vom Benutzer durch nur erzählen Sie das Verhalten(interface).
Ihre intuition ist korrekt; der Typ einer Variablen sollte so spezifisch wie möglich.
Dies ist im Gegensatz zu Methode Rückgabetypen und parameter-Typen; es API-Designer wollen ein wenig Abstrakt, so dass die API können flexibler sein.
Variablen sind nicht Teil des APIs. Sie sind Implementierungsdetails. Abstraktion in der Regel nicht gelten.
modeOfTransport1
undmodeOfTransport2
, dann deklarieren Sie als Schnittstelle Instanzen eher als konkrete Instanzen erforderlich ist.Mit "IVehicle modeOfTransport1 = new Auto();", Methoden besaß nur mit dem Auto nicht zugänglich sind modeOfTransport1. Ich weiß nicht, der Grund trotzdem.
Car
. Die Referenz gespeichert inmodeOfTransport1
umgewandelt werden kann, um eineCar
(wenn Sie geschehen, zu wissen, dass diese spezielle Instanz derIVehicle
ist, in der Tat, einCar
) und alleCar
-spezifische Instanz-Methoden sind dann aufrufbar.new Car()
verhält (oder Verhalten möglicherweise) unterschiedlich, je nach dem, was auf der linken Seite der Zuweisung Anweisung, und das ist einfach nicht wahr.instanceof
zu testen, ob der Verweis umgewandelt werden kann zu einer bestimmten Klasse oder Schnittstelle. Wenn Sie erklärenIVehicle thing = new Car()
, der Grund können Sie nicht nennenCar
-spezifische Methoden ist, dass Sie oder vielmehr der compiler nicht wissen, diething
passiert zu seinCar
(obwohl es ist), weil es nicht erklärt werden, ein Auto. Allerdings können Sie mitif (thing instanceof Car) { /* cast to Car and call car-specific methods */ }
. Beachten Sie, dass das casting eine Referenz-variable auf einen anderen Typ nimmt keine änderungen am referenzierten Objekt selbst, sondern nur die Referenz.