簡體   English   中英

為什么Java編譯器決定是否可以基於“引用”類型調用方法而不是實際的“對象”類型?

[英]Why does Java compiler decide whether you can call a method based on the “reference” type and not on actual “object” type?

我只是想知道為什么Java編譯器決定是否可以調用基於“引用”類型的方法而不是實際的“對象”類型? 為了解釋我想引用一個例子:

class A {
void methA() {
    System.out.println("Method of Class A.");
} 
}

class B extends A {
void methB() {
    System.out.println("Method of Class B.");
}
public static void main(String arg[]) {
    A ob = new B();
    ob.methB();       // Compile Time Error
}
}

這將產生編譯時錯誤,即方法methB()class A找不到,盡管對象引用“ob”包含由方法methB()組成的class B的對象。 原因是Java Compiler檢查Class A (引用類型)中的方法而不是Class B (實際對象類型)。 所以,我想知道這背后的原因是什么。 為什么Java Compiler在Class A中查找方法,為什么不在Class B中(實際的對象類型)?

假設你有一個Animal類和一個擴展 AnimalDog類。 現在,如果Animal定義了一個名為speak()的方法,Dog定義了一個名為bark()的方法。 如果您這樣做:

Animal a = new Dog();

這意味着你指着一只狗並說它是一只動物。 當您將狗視為動物(而不是狗)時,您只能調用為動物定義的方法,而不是狗。

在編譯期間,編譯器會檢查是否在引用類型中定義了被調用的方法。

通過將變量聲明為A類,您基本上隱藏了它實際上是一個子類型的事實。 沒有看到類型B的方法是標准行為,這在(嚴格類型的)面向對象中是必不可少的。

很簡單,編譯器不知道變量的類型。 與上面描述的場景不同,實際的“對象”類型通常並不明顯。 這就是“對象”類型是運行時類型的原因:它在運行時已知。

想象一下像這樣的方法:

public static void process(A ob) {
    ob.methB(); //how do you know if this is valid?
}

public static void main(String[] args) {
    process(new B()); //would make the above call valid
    process(new A()); //would make the above call invalid
}

簡而言之,您允許變量具有使您的調用無效的運行時類型。 可能是有效的,但如果依賴於methB() ,則必須將B作為參數。

回到你的代碼示例,這個例子沒有任何意義:

A ob = new B();
//why would you declare ob as A if you are storing a B inside it
//this is only useful if you want to store different types of objects in it at some point
//however, that's not the case, because in the next line:
ob.methB(); //you're calling methB()

你的疑問很好,但它是一種哎呀。 您正在為超類分配一個子類對象,因此我將只向調用者公開超類的方法。

簡單地說,假設A類作為具有2個方法和B的接口是實現類,其中包含10個方法。 但是如果你嘗試用接口A為該類創建對象,它將只暴露2個方法。 在您的情況下應用相同的邏輯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM