繁体   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