2017-07-15 79 views
0

我知道,無論實際的對象是什麼,引用變量指的是,我可以調用引用的方法取決於變量的聲明類型(在代碼的第15行)。我想知道爲什麼這樣。爲什麼類用戶不能使用Shape類型的引用變量s來調用它的子類方法drawCircle()?爲什麼我們不能使用超類的引用變量來訪問其子類的方法(在超類中不可用的方法)?

public class Shape{ 
      public void displayShape(){ 
       System.out.println("shape displayed"); 
         } 
    public class Circle extends Shape{ 
      public void drawCircle(){ 
       System.out.println("circle drawn"); 
         } 
    public class Test{ 
      p.s.v.main(String[] a){ 
      Circle c=new Circle(); 
      Shape s=new Shape(); 
      display(c); 
      display(s); 
      public void display(Shape myShape){ 
       myShape.displayShape();//possible for ref variable c and s 
       myShape.drawCircle();//not possible for reference var s 
       } 
      } 
     } 

u能爲我提供的對象級別會發生什麼解釋?我是新來的Java。

+0

更正您的代碼並編寫完整代碼不要使用像這裏使用的快捷方式「p.s.v」而不是寫入public static void main(String args [])。另外還有更多的錯誤,所以請重新構造一次代碼。如果要實現這樣的功能,Java中不允許嵌套函數使用Java 8的lambda表達式。 –

回答

0

編譯器只是知道myShapeShape類型的基準變量,其僅包含一個方法displayShape(),所以根據編譯器,它是不可能的調用方法drawCircle()其中Shape類不包含。

編譯器不關心這個變量在運行時會保存什麼對象。您可以在稍後的某個時間點從Shape類擴展另一個類,並使用myShape引用來保存該子類對象。編譯器只關心編譯時myShape的類型。

如果您Circle類碰巧覆蓋displayShape()方法,如下圖所示:

public class Circle extends Shape { 
    public void displayShape() { 
     System.out.println("I am a Circle!"); 
    } 

    public void drawCircle() { 
    // Implementation here 
    } 
} 

在運行時發生的唯一決定是哪個displayShape()方法調用。

0

首先,你忘了製作Circle的子類Shape

然後你說:

我可以在引用調用的方法是依賴於聲明 類型的變量

Shape myShape參數也是一個變量:

public void display(Shape myShape){ 
    ... 
    myShape.drawCircle(); 
} 

所以在這裏,對於局部變量或字段變量,編譯器r僅使用聲明的類型來綁定調用的方法。
並且由於Shape類用作聲明變量的類型,因此只能調用此類的方法。

+0

甚至不可能調用display方法,它的聲明不知何故,這似乎是他的問題。 – user3734782

+0

@ user3734782它是正確的。我不認爲這是它的問題,即使這可能是誤導。我認爲這只是一個非常近似的僞代碼。你也有'p.s.v.main(String [] a){'和'display'應該是靜態方法。但是... – davidxxx

0

如果你確信是MyShape的,你可以明確地將其轉換爲一個 ((Circle)myShape).drawCircle();Circle myCircle = (Circle)myShape; myCircle.drawCircle();一個圈,但如果你做到這一點,它實際上不是一個Circle那麼你會得到一個ClassCastException

一般來說,你想嘗試並避免這種類型的鑄造,儘管它的代碼氣味的東西,這表明你的設計是有點關閉。 (有時你需要這樣做,但它沒有利用多態性)。

要利用多​​態的,你反而會具有Shape定義displayShape()作爲一個抽象的方法,然後代替drawCircle()drawSquare()等等的Shape每個子類都會有自己的displayShape()方法的版本,而在Shape本身你將有: public abstract displayShape();這是一種告訴編譯器「我所有的子類都有這個displayShape()方法,所以當有人在我之中調用displayShape()時,使用該子類中定義的方法」。

因此,例如:

Shape myCircle = new Circle(); 
Shape mySquare = new Square(); 
myCircle.displayShape(); //draws a circle 
mySquare.displayShape(); //draws a square 

//And if you can't choose which one you want... 
Shape surpriseMe = new Random().nextBoolean() ? myCircle : mySquare; 
surpriseMe.displayShape(); //draws either a circle or a square! 
0

如何reading about polymorphism

public abstract class Shape { 
    public abstract void draw(); 
} 

public class Circle extends Shape { 
    @Override 
    public void draw() { 
     System.out.println("Circle drawed"); 
    } 
} 

public class Triangle extends Shape { 
    @Override 
    public void draw() { 
     System.out.println("Triangle drawed"); 
    } 
} 

public class Test() { 
    public static void display(Shape shape) { 
     shape.draw(); 
    } 

    public static void main(String[] args) { 
     //how can you define "shape" in real world? its triangle or... -> abstraction 
     Circle c = new Circle(); 
     Triangle t = new Triangle(); 

     display(c); 
     display(t); 
    } 
} 
相關問題