2016-06-23 23 views
1

Ich habe den Code:Unterschied zwischen den verschiedenen Möglichkeiten, in ein Objekt in Java Instanziieren

class Father{ 
    String name="father"; 
    void f(){System.out.print("father class");} 
} 

class Son extends Father{ 
    String name = "son"; 
    void f(){System.out.print("son class");} 
    void f2(){} 
} 

public class Test { 

    public static void main(String[] args) { 
     Father s = new Son(); 
     System.out.println(s.name);// outputs father 
     s.f();// outputs "son class" 
     s.f2();// s does not have f2 
    } 

} 

Meine Frage ist, was ist der Unterschied s = new Vater zwischen tun Vater() oder, Vater s = new Sohn () oder, Sohn s = neuer Sohn()?

Also, warum verursacht s.f2 im Beispiel einen Fehler? Muss Vater f2() implementieren?

+0

Sie instanziieren 's' als allgemeiner Typ' Vater'-Objekt, obwohl es unter der Haube wirklich ein 'Sohn' ist, ein bestimmter Typ (Unterklasse)' Vater'. Da der Typ von 's', wie Java es sieht,' Vater' ist, und die 'Vater' Klasse keine Methode' f2() 'hat, haben Sie einen Fehler. –

+0

Es ist kein allgemeinerer Objekttyp, das * Objekt * ist immer noch ein 'Sohn', es wird nur einer * Variablen * vom Typ' Vater' zugewiesen. – azurefrog

+2

P.S. Ich kenne die Anwendung nicht, aber macht es nicht mehr Sinn, dass alle Väter Söhne sind, aber nicht alle Söhne Väter sind? –

Antwort

1

ich denke, dass es einfacher ist, mit einem Tier Beispiel zu erklären:

class Animal { 

    void printName() { 
     System.out.println("Animal"); 
    } 
} 
class Dog extends Animal{ 

    @Override 
    void printName() { 
     System.out.println("Dog"); 
    } 
} 
class Cat extends Animal{ 

    @Override 
    void printName() { 
     System.out.println("Cat"); 
    } 

    void meow() { 
     System.out.println("meow"); 
    } 
} 

Wenn Sie Klassen erweitern, th Die untergeordnete Klasse kann die Methoden des übergeordneten Elements überschreiben und eigene Methoden verwenden. In meinem Animal-Beispiel kann das generische Animal-Objekt nur seinen Namen angeben, aber das Cat-Objekt kann seinen Namen und auch Miau geben. Offensichtlich ist die Miau-Methode spezifisch für Cat, da wir wissen, dass Hunde im Allgemeinen nicht Miauen und Tiere können.

Wenn Sie das tun

Animal animal = new Cat(); 

Sie tatsächlich eine Instanz der Katze schaffen, sondern es als allgemeines Tier verwenden. Daher verfügt Ihre Tierinstanz nur über Methoden, die in der Animal-Klasse verfügbar sind, aber die Ausführung der Methoden, die von der Cat-Klasse überschrieben werden, wird an die Cat-Klasse delegiert. wenn Sie Katzen spezifische Methoden ausführen möchten, dann müssen Sie Ihr Tier auf die Katze

(Cat) animal.meow(); 

In Ihrem Beispiel werfen f2() -Methode Sie Ihren Vater Objekt an den Sohn werfen anrufen müssen zuerst

(Son)s.f2(); 
0

s.f2() ist der Syntaxfehler, weil Sie JVM gesagt haben, dass s Vater, nicht Sohn ist.

Im Code, kann es nicht f2 Methode in Vater Klasse

class Father{ 
    String name="father"; 
    void f(){System.out.print("father class");} 
} 

Aber es bedeutet nicht, finden Sie den Code falsch ist, sondern nur die JVM es nicht mag.

wenn Sie s.f2() zu

(Son)s.f2(); 

ändern wird es funktioniert

1

Was ist mit Ihnen zu tun hat ist Referenztyp (Variablentyp) und Objekttyp (was ist eigentlich bezeichnet wird) . Der Java-Compiler benötigt eine Art Garantie, dass das Objekt, auf das verwiesen wird, die von Ihnen aufgerufene Methode ausführen kann. Um dies zu tun, sieht es nach der Referenztyp. Bei der Ausführung ist der Methodenablauf der Objekttyp. setzen

einfach:

Father f = new Father(); //Treated as a Father, behaves like a Father 
Son s = new Son();  //Treated as a Son, behaves like a Son 
Father q = new Son(); //Treated as a Father, behaves like a Son (sounds like my own father) 

Wenn Sie werfen q einen Sohn von (Son)q sagen, wird es als Son vom Compiler behandelt werden, es sei denn, das Objekt nicht ist tatsächlich ein Sohn, In diesem Fall erhalten Sie eine ClassCastException.

1

Lassen Sie uns ein einfacheres Konzept nehmen, da der Hierarchie bedeutet, dass alle Son s sind Father s, aber nicht alle Father s sind Son s (was nicht ganz richtig ist).

Lassen Sie uns die abstrakte Klasse nehmen Number und alle seine Kinder - der Kürze halber, wir Integer, Float und BigInteger verwenden können.

Angenommen, wir erklären dies:

Number num = Float.NaN; 

Wir haben jetzt eine Float Instanz, die von einem Float verwiesen wird. Wir können alles tun, was wir zu dieser Instanz wollen, aber nur im Zusammenhang mit einer Number.

Es gibt eine nützliche Methode für FloatisNan genannt, die uns unsere Schwimmer erlauben würde, zu sehen, ob tatsächlich eine Zahl ist. Im Kontext von Number ... existiert diese Methode nicht.

Es gibt Vorteile, dies zu tun - wenn Sie die Spezifität der Kindverweis nicht benötigen, können Sie auf alles durch seine Elternklasse (oder Schnittstelle) beziehen. Dies entkoppelt Sie auch von der API des Kindes, wenn Sie von ihm abgekoppelt werden wollen (siehe developing to an interface).

0

OK Ich sehe, wo ist die Verwirrung hier.

in Java Sie Methoden außer Kraft setzen können, aber nicht Klassenvariablen

diese Regel im Auge behalten

Also, wenn Sie

tun

Vater s = new Son();

das Objekt „s“ ist vom Typ Vater

und wie wir die Variablen innerhalb gesagt wird nicht nur die Methoden Also das ist das Endergebnis ein Objekt überschrieben werden, die Elementvariablen vom Vater hat Klasse (die Variable "Name") und die Methode aus der Sohnklasse (da Vater nur 1 Methode und Sohn außer Kraft gesetzt hatte).

und warum die f2 nicht funktioniert

es ist, weil das Objekt „s“ vom Typ Vater nicht Sohn ist (es ist Vater-Objekt, das ein Verfahren davon durch Sohn Klasse anders als das überschrieben es wird halten Vater Objekt sein) und Vater nicht über f2 Methode ist, warum Sie den Fehler der Kompilierung bekommen