超类引用子类对象?

时间:2010-03-29 02:53:11

标签: java oop

给我一​​个我们需要在Java中使用超类引用子类对象的情况。请给我一个实时的例子。

THX

9 个答案:

答案 0 :(得分:5)

我知道这已经过时了但是这个项目出现在我最近一直在做的项目上(只是一个初级开发人员做出了意想不到的事情 - 没有实际的理由!)我认为有些答案错过了点..

这与正常多态性无关;我认为这个问题与代码如下所示:

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

其中子类用于超类的定义。据我所知,没有合理的理由自己编写类似的东西,但是语言允许你这样做的原因是它需要一些核心Java类,例如: Object

例如,虽然它没有存储对它的引用,但Object的代码在其默认的String方法中创建并返回toString对象,但{{1} }}是String的子类。

有趣的是,虽然技术上允许,但是让超类在其构造函数中创建子类实例是没有意义的。

e.g。

Object

这会因为它创建一个无限循环而崩溃,因为B的构造函数正在调用A的构造函数,它正在调用B的构造函数等。

答案 1 :(得分:2)

充分利用多态性......你必须完全理解多态性才能真正体会到这一点......你可以根据需要使用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());
    }

    }
}

我希望我对此没有错......只是一个想法!

答案 2 :(得分:2)

这个问题似乎不太正确......在父类中对子类进行显式引用似乎是打破层次结构和库的意图。

一旦父类开始携带对子类的引用,父类依赖于知道它的后代;这很糟糕。

除非问题在这里被错误引用,否则我会说你的面试官正在通过他的帽子说话。

答案 3 :(得分:1)

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
}

现在,如果德国人开始有黑发,我重新编译德语类,而主()完全不知道德国人是如何改变的。主要方法继续工作,好像什么也没发生过,打印成黑色 请原谅最小的语法和语法

答案 4 :(得分:1)

使用这种赋值,你不能在超类中调用重载方法。

  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);
    }

}

答案 5 :(得分:0)

呃,任何时候?如果您有类似多态链接列表的内容:

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替换原则指出子类的行为应该与它们的超类完全相同,因此您可以在使用超类的任何地方替换子类。

答案 6 :(得分:0)

这是一个重要且最有启发性的例子:java.lang.reflect.Array

  

Array类提供动态创建和访问Java数组的静态方法。

  • getLength(Object array)
    • 以int。
    • 的形式返回指定数组对象的长度
  • get(Object array, int index)
    • 返回指定数组对象中索引组件的值。
  • set(Object array, int index, Object value)
    • 将指定数组对象的索引组件的值设置为指定的新值。

数组以Object传递,这是所有数组类型的超类。这是必要的,因为我们正在做反思:我们并不总是知道在编译时数组类型是什么。

答案 7 :(得分:0)

这真的很奇怪,因为它可能有用的情况类型(例如提供单例对象的自定义实现)具有更好的替代方案;特别是服务加载器机制。

在伪装的全局变量世界之外,你确实倾向于遇到循环引用的问题。 (考虑到子类字段中的超级引用指向封闭的超级实例,而超级实例又是子类中的引用...)

答案 8 :(得分:0)

我认为如果类及其子类共享某种类型的子父关系并且子类具有对其父类的引用,就会发生这种情况,类似这样

public interface Node
{   
    String getName();

    int getValue();

    Container getParentContainer();
}

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

我很想知道如何以更好的方式设计它来解决这个问题。