簡體   English   中英

超類引用子類對象?

[英]Super class reference to a sub class object?

給我一個我們需要在Java中使用超類引用子類對象的情況。請給我一個實時的例子。

謝謝

我知道這已經過時了但是這個項目出現在我最近一直在做的項目上(只是一個初級開發人員做出了意想不到的事情 - 沒有實際的理由!)我覺得有些答案錯過了這一點。

這與正常的多態性無關; 我認為這個問題與代碼如下所示:

class A {
    B b; //odd reference here..
}
class B extends A {
}

其中子類用於超類的定義。 據我所知,沒有合理的理由自己編寫類似的東西,但是語言允許你這樣做的原因是它需要一些核心Java類,例如Object

例如,盡管它沒有存儲對它的引用,但Object的代碼在其默認的toString方法中創建並返回一個String對象,但是, StringObject的子類。

有趣的是,雖然它在技術上是允許的,但是讓超類在其構造函數中創建子類實例是沒有意義的。

例如

class A {
    B b;
    A(){
        b = new B();
    }
}
class B extends A {
}

這會因為它創建一個無限循環而崩潰,因為B的構造函數正在調用A的構造函數,它正在調用B的構造函數等。

要充分利用多態性......你必須完全理解多態性才能真正理解這一點......你可以使用適當的Interface實際上實現相同的行為,所以他們說...

abstract class Shape {

    abstract double getArea();

}

class Rectangle extends Shape{
    double h, w;

    public Rectangle(double h, double w){

        this.h = h;
        this.w = w;
    }

    public double getArea(){
        return h*w;
    }
}

class Circle extends Shape{
    double radius;

    public Circle(double radius){
        this.radius = radius;
    }

    public double getArea(){
        return Math.PI * Math.sqrt(radius);
    }
}

class Triangle extends Shape{
    double b, h;

    public Triangle(double b, double h){
        this.b = b;
        this.h = h;
    }

    public double getArea(){
        return (b*h)/2;
    }


}

public class ShapeT{
    public static void main(String args[]){

    //USAGE
    //Without polymorphism
    Triangle t = new Triangle(3, 2);
    Circle c = new Circle(3);
    Rectangle r = new Rectangle(2,3);

    System.out.println(t.getArea());
    System.out.println(c.getArea());
    System.out.println(r.getArea());

    //USAGE with Polymorphism

    Shape s[] = new Shape[3];
    s[0] = new Triangle(3, 2);
    s[1] = new Circle(3);;
    s[2] = new Rectangle(2,3);

    for(Shape shape:s){
        System.out.println(shape.getArea());
    }

    }
}

我希望我對此沒有錯......只是一個想法!

這個問題似乎不太正確......在父類中對子類進行顯式引用似乎是打破層次結構和庫的意圖。

一旦父類開始攜帶對子類的引用,父類依賴於知道它的后代; 那很不好。

除非問題在這里被錯誤引用,否則我會說你的面試官正在通過他的帽子說話。

使用這種賦值,你不能在超類中調用子類中的重載方法。

  public class Reference {


    public static void main(String args[]){
        A a = new B();
        //B b = new A(); // You can not do this, compilation error
        a.msg(); // calls the subclass method
        ((B)a).msg("Custom Message"); // You have to type cast to call this
        System.out.println(a.getClass());
        if(a instanceof B){//true
            System.out.println("a is instance of B");
        }
        if(a instanceof A){//true
            System.out.println("a is instance of A also");
        }


    }
}

class A{
    public void msg(){
        System.out.println("Message from A");
    }
}

class B extends A{
    public void msg(){//override
        System.out.println("Message from B");
    }
    public void msg(String msg){//overload
        System.out.println(msg);
    }

}
class Person
String hairColor = "default_noColor";
-----------------------------
class German extends Person
String hairColor = "brown";
-----------------------------
class Scandinavian extends Person
String hairColor = "red";
-----------------------------
public static void main(String args[]) {
    Person p = new Person();
    German g = new German();
    Scandinavian s = new Scandinavian();
    sysout p.hairColor // prints default_noColor
    if (cond1) {
        p = g;
    }
    sysout p.hairColor // prints brown
    else if (cond2) {
        p = s;
    }
    sysout p.hairColor // prints red
}

現在,如果德國人開始有黑發,我重新編譯德語類,而主()完全不知道德國人的變化。 主要方法繼續工作,好像什么也沒發生過,打印成黑色。
請原諒最小的語法和語法

呃,任何時候? 如果您有類似多態鏈接列表的內容:

class Node {
   has 'next' => ( isa => 'Node' );
}

class TextNode extends Node {
   has 'text' => ( isa => 'Str' );
}

class ImageNode extends Node {
   has 'image' => ( isa => 'Image' );
}

然后你可以這樣做:

TextNode->new( 
    text => 'Here is my cat:', 
    next => ImageNode->new(
        image => 'nibbler.jpg',
        next  => undef,
    ),
);

您的具體情況涉及Node保存對TextNode或ImageNode的引用,這在Java中可能很好:

 Node->new( next => TextNode->new ( ... ) )

雖然我會讓Node在具有該功能的語言中扮演角色......但這個想法基本相同。

Liskov替換原則指出子類的行為應該與它們的超類完全相同,因此您可以在使用超類的任何位置替換子類。

這是一個重要且最有啟發性的例子: java.lang.reflect.Array

Array類提供動態創建和訪問Java數組的靜態方法。

  • getLength(Object array)
    • 以int形式返回指定數組對象的長度。
  • get(Object array, int index)
    • 返回指定數組對象中索引組件的值。
  • set(Object array, int index, Object value)
    • 將指定數組對象的索引組件的值設置為指定的新值。

數組作為Object傳遞, Object是所有數組類型的超類。 這是必要的,因為我們正在進行反射:我們並不總是知道在編譯時數組類型是什么。

這真的很奇怪,因為它可能有用的情況類型(例如提供單例對象的自定義實現)有更好的替代方案; 特別是服務加載器機制。

在偽裝的全局變量世界之外,你確實會遇到循環引用的問題。 (考慮到子類字段中的超級引用指向封閉的超級實例,而超級實例又是子類內的引用...)

我認為如果類及其子類共享某種類型的子父關系並且子類具有對其父類的引用,則會發生這種情況,類似這樣的

public interface Node
{   
    String getName();

    int getValue();

    Container getParentContainer();
}

public interface Container extends Node
{   
    Set<Node> getChildren();
}

我很想知道如何以更好的方式設計它來解決這個問題。

暫無
暫無

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

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