type-casting, wenn Objekte des interface-Referenzen in Java
Ich bin vertraut mit type casting
im inheritance model
.
Lassen SuperClass and SubClass
werden Eltern-und Kind-Klassen;
SuperClass superClass = new SubClass()
; -- Hier die object
instanziiert ist ein subclass object
;
aber seine reference type
ist SuperClass
; das ist nur die methods
von SuperClass
genannt werden kann, auf die subclass object
; Jede methods
sind nicht inherited/overridden
im subclass
kann nicht aufgerufen werden (das ist eine beliebige, eindeutige methods
von subclass
).
Beobachtete ich dasselbe Verhalten wie oben, wenn SuperClass is an interface
und SubClass implements it
. Das ist nur die Methoden deklariert, die in SuperClass interface
verfügbar sind, genannt zu werden, auf die SubClass
Objekt. Ist mein Verständnis richtig? Aber mit einigen casting
kann ich nennen methods
ist nicht Teil der Schnittstelle, die ich beobachtet habe, in meinem Beispiel-code unten;
Habe ich einige Kommentare auf meinem Verständnis, wie es funktioniert;
aber ich würde gerne wissen ob die Sinn machen oder, wenn meine interpretation falsch ist;
class Animals {
public void bark(){
System.out.println("animal is barking");
}
}
interface catIF {
public void catting();
}
interface dogIF {
public void dogging();
}
class Dog extends Animals implements dogIF {
public void bark(){
System.out.println("dog is barking");
}
public void dogging() {
System.out.println("dogging");
}
}
class Cat extends Animals implements catIF {
public void bark(){
System.out.println("cat is barking");
}
public void catting() {
System.out.println("catting");
}
}
public class Animal {
public static void main(String[] args){
dogIF dog = new Dog();
//dog.bark(); this fails
//This method actually actually exists;
//but it is not available or hidden because dogIF reference
//limits its availability; (this is similar to inheritance)
Dog dog2 = new Dog();
dog2.bark();
////prints dog is barking
Animals an =(Animals) dog;
an.bark();
//prints dog is barking
//by casting we mean, treat the dog as an animals reference
//but the object itself is a dog.
//call the bark() method of dog
//but dog did not have this method in the beginning (see first line
//in main - when instantiated with interface type)
}
}
dogIF#bark()
nicht vorhanden, so sind Sie Recht haben. Methodenaufrufe sind entschlossen, zur compile-Zeit, basierend auf der deklarierte Typ der Referenz.- Ja Ihr verstehen, ist das völlig in Ordnung.
- Vererbung, ob die Schnittstellen ist ein wenig flockig in Java -- ich bin nicht sicher, ob jemand wirklich versteht. (Verstanden hab ich es lange genug, um zu implementieren
checkcast
, aber die Regeln sind also Arkan hab ich längst vergessen.) - Aber eine Sache zu verstehen ist, dass wenn du einen expliziten cast (
(Animals)
, z.B.), dann wird der compiler nimmt Ihr Wort für es, dass das Objekt in Frage ist der Typ angegeben. Unter der Decke eincheckcast
bytecode versichert, dass das, was Sie sagen, wahr ist, aber der compiler hat keine Ahnung, ob diecheckcast
Erfolg haben oder scheitern. - eine Art von expliziten cast compiler fängt ihn auf. aber einige throws classcastexception-Fehler in run-time...ich denke, der Grund, warum diese explizite cast gefangen sind in compile-Zeit ist, denn diese wirft nie passieren kann. so etwas wie
Cat cat = (Dog) dog
; im obigen Beispiel; Obwohl beide erstreckt sich vonAnimals
- Wirft überprüfen, ob das Objekt implementiert die neue Art, bevor Sie wirksam werden, und werfen einen
ClassCastException
wenn es nicht. Also, entwederCat
oderDog
erweitert/implementiertAnimals
und umgewandelt werden kannAnimals
, aber Sie haben nicht die super - /Unterklasse-Beziehung zu einander, so können Sie nicht wirken einem zum anderen. Obwohl Sie haben könnte, ein Objekt, das erweiterteCat
und umgesetztdogIF
, wenn Sie wollte beschreiben, wie eine Katze, teilte das letztere Verhalten mit Hunden... wie bei mir, die manchmal einen ball Holen. - Explizite Typumwandlungen sind nicht "gefangen" werden zur compile-Zeit. Was diagnostiziert beim kompilieren wird eine inkompatible Zuordnung.
Cat cat = (Dog) dog
ist nicht mehr unwirksam, die für den compiler, als Cat Cat = (Hund) anotherCat. What the compiler diagnoses is the attempt to assign something declared (by the cast) to be Dog to a Cat variable. (The compiler would be perfectly happy with
Katze Katze = (Katze) Hund`.)
Du musst angemeldet sein, um einen Kommentar abzugeben.
Vererbung von Schnittstellen ist wirklich nicht "flockig" oder kompliziert. Sie Verhalten sich genau so, wie abstrakte Klassen, mit den Ausnahmen, verweisen Sie Sie anders (implements statt extends) und dass Sie erlaubt sind, um zu Erben, so viele Schnittstellen, wie Sie, sondern kann nur eine direkte Oberklasse (Abstrakt oder nicht).
Als mit anderen-Vererbung: Wenn alles, was Sie wissen über ein Objekt ist, dass es eine Schnittstelle implementiert, dann kann man nur zugreifen über die Schnittstelle. Wenn Sie wissen, dass es implementiert eine andere Schnittstelle oder für einen bestimmten übergeordneten Klasse oder eine Instanz einer bestimmten Klasse ist, dann können Sie werfen es denen und durch die exponierte Mitglieder von denen.
So, ja: Wenn alle Ihr Programm weiß, ist, dass das Objekt eine Instanz der
Animals
, dann alles, was Sie tun können, ist anrufen was erklärt, auf Tiere. Das bedeutet, dassbark()
plus was auch immer Methoden, die Sie erbt vonObject
(da ist alles einObject
direkt oder indirekt, auch wenn das nicht explizit angegeben).Wenn Ihr Programm weiß, dass das Objekt eine Implementierung von
dogIF
odercatIF
- weil der Variablentyp sagt, es ist, oder weil Sie haben erfolgreich typecast es an einer dieser Schnittstellen-Sie können auch rufen Sie die Methode(s) erklärte, die von diesen Schnittstellen. By the way, die üblichen Konventionen für die Schnittstellen zu benennen, wie die Klassen, mit UppercasedFirstLetter... da Sie in vielen Fällen den Unterschied zwischen einem interface und einer Klasse ist nicht wirklich von Bedeutung, um die Leute verwenden es.Wenn Ihr Programm passiert, um zu wissen, dass das Objekt eine
Dog
ist, rufen Sie alles, was es erbt von entwederAnimals
oderdogIF
oder direkt vonDog
. Natürlich könnte es tatsächlich eineChihuahua
(Unterklasse von Hund), aber das ist OK, die Unterklasse reagieren auf alles, was der Superklasse würde geantwortet haben, in "den richtigen Weg zur Erhaltung der Semantik". (Das heißt, eineChihuahua
reagieren kann, umbark()
mit den Worten: "yip yip yip grr yip!", aber diese Methode sollten wirklich nicht führen, versuchen Sie, beißen Ihre Knöchel.)Hoffe, das hilft. Es ist wirklich nicht so kompliziert.
If your program happens to know that the object is a Dog, you can call anything it inherits from either Animals or dogIF, or that is provided directly by Dog
-- nur möglich, wenn ich erkläreDog dog = new Dog(); but not Animals dog = new Dog() or dogIF dog = new Dog()
Dog
- entweder, weil Sie es erstellt haben, oder weil Sie wissen, dass von anderen Zusammenhang, oder weil Sie gerade verwendet dieinstanceof
Betrieb zu überprüfen-Sie können sicher typecast es zuDog
und Sie als solche behandeln. Ich gebe zu, dass ich shorthanded ein bisschen.dogIF dog = new Dog()
; Das Objekt ist einDog object
; aber dies ist nicht erlaubt:(Dog)dog.bark()
. Ich denke, ich habe einige Missverständnisse hier..dogIF
umgewandelt werden kannDog
-- aber das bedeutet nur, dass die Besetzung wirft classcastexception-Fehler, wenn das Objekt nicht eine Instanz von dem, was er gewirkt. Wenn Sie ist eine Instanz vonDog
, es ist nichts falsch mit der festgelegten... obwohl Sie müssen vorsichtig sein, um sicherzustellen, dass Sie Gießen das Objekt, sondern das Ergebnis. Versuchen((Dog)dog).bark()
.checkcast
... und bekommen es zu passieren, die Sonne acceptance test. Es gibt mehrere nicht-offensichtliche Wendungen.invokeinterface
interne Umsetzung (die ist ein bisschen chaotisch und langsam). Könnte man irgendwie herausfinden, wie deren Umsetzung zu verändern, von den änderungen in der Spezifikation.