Java 超类引用子类对象?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2535550/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 09:00:03  来源:igfitidea点击:

Super class reference to a sub class object?

javaoop

提问by JavaUser

Give me a situation where we need to use the super class reference to a subclass object in Java.Please give me a real time example.

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

Thx

谢谢

回答by jrockway

Uh, any time? If you have something like a polymorphic linked list:

嗯,随时?如果你有类似多态链表的东西:

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

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

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

Then you can do:

然后你可以这样做:

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

Your specific situation involves Node holding a reference to TextNode or ImageNode, which is probably fine in Java:

您的具体情况涉及 Node 持有对 TextNode 或 ImageNode 的引用,这在 Java 中可能没问题:

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

Though I would make Node a role in languages with that feature... the idea is largely the same.

尽管我会让 Node 在具有该功能的语言中扮演一个角色……但想法大致相同。

The Liskov substitution principle states that subclasses should behave exactly like their superclasses, so you can substitute a subclass anywhere the superclass is used.

Liskov 替换原则指出子类的行为应该与其超类完全相同,因此您可以在使用超类的任何地方替换子类。

回答by ultrajohn

To Take Full Advantage of polymorphism...You have to understand polymorphism fully for you to really appreciate this... You can actually achieve the same behavior using an Interfaceas appropriate, so they say...

充分利用多态性......你必须完全理解多态性才能真正理解这一点......你实际上可以使用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());
    }

    }
}

I hope I'm not wrong on this... just a thought!

我希望我没有错……只是一个想法!

回答by polygenelubricants

Here's an important and most instructive example: java.lang.reflect.Array:

这是一个重要且最具启发性的示例java.lang.reflect.Array

The Arrayclass provides static methods to dynamically create and access Java arrays.

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

  • getLength(Object array)
    • Returns the length of the specified array object, as an int.
  • get(Object array, int index)
    • Returns the value of the indexed component in the specified array object.
  • set(Object array, int index, Object value)
    • Sets the value of the indexed component of the specified array object to the specified new value.
  • getLength(Object array)
    • 以 int 形式返回指定数组对象的长度。
  • get(Object array, int index)
    • 返回指定数组对象中索引组件的值。
  • set(Object array, int index, Object value)
    • 将指定数组对象的索引组件的值设置为指定的新值。

Arrays are passed around as Object, which is the superclass of all array types. It's necessary because we're doing reflection: we don't always know what the array type will be at compile time.

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

回答by Everyone

That question doesn't seem quite right ... putting an explicitreference to a child-class in the parent-class seems like an intent to break the hierarchy and the library.

这个问题似乎不太正确......在父类中明确引用子类似乎是为了打破层次结构和库。

As soon as the parent-class starts to carry a reference to the child-class, the parent-class is dependant upon knowing it's descendants; that is bad.

一旦父类开始携带对子类的引用,父类就依赖于知道它的后代;那很不好。

Unless the question was misquoted here, I'd say your interviewer was talking through his hat.

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

回答by user268396

It's really rather odd because the type of situation where it might be useful (supplying a custom implementation of a singleton object for instance) has betteralternatives to that; in particular the service loader mechanism.

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

And outside the world of globals in disguise you do tend to run into issues with circular references. (Consider that the super reference within your sub-class field points to the enclosing super instance which in turn is a reference from within the sub-class ...)

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

回答by seb

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
}

now, if germans start having black hair, i recompile class German and the main() is totally agnostic of how the German has changed. The main method continues to work as if nothing ever happened and prints black.
Kindly excuse minimal grammar and syntax

现在,如果德国人开始有黑头发,我会重新编译德语班级,并且 main() 完全不知道德国人的变化情况。main 方法继续工作,就好像什么都没发生过一样,打印出黑色。
请原谅最少的语法和语法

回答by Mark Rhodes

I know this is old but this cropped up on a project I've been working on recently (just a junior developer doing something unexpected - there was no actual reason for it!) and I think some of the answers have missed the point..

我知道这是旧的,但这突然出现在我最近从事的一个项目中(只是一个初级开发人员做了一些意想不到的事情 - 没有真正的原因!)而且我认为一些答案没有抓住重点..

This has nothing to do with normal polymorphism; I think the question relates to the case where the code looks like this:

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

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

Where the sub-class is used in the definition of the super-class. As far a I can tell there is no legitimate reason for coding something like this yourself, however the reason the language allows you to do this is that it's required for some of the core Java classes e.g. Object.

其中子类用于超类的定义。据我所知,自己编写这样的代码是没有正当理由的,但是该语言允许您这样做的原因是某些核心 Java 类(例如Object.

For example, although it doesn't store a reference to it, the code for Objectcreates and returns a Stringobject in it's default toStringmethod, however, Stringis a sub-class of Object.

例如,虽然它不存储对它的引用,但用于在其默认方法中Object创建和返回String对象的代码是.toStringStringObject

It's interesting to note that although it's technically allowed, it doesn't make sense to have a superclass create a subclass instance in its constructor.

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

e.g.

例如

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

This will just crash due to the fact that it creates an infinite loop, since B's constructor is calling A's constructor, which is calling B's constructor etc..

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

回答by Neil

Using this kind of assignment you can not call the overloaded method in the subclass which is not in super class.

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

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

}

回答by themanwhosoldtheworld

I think this can happen if the class and its subclass share child parent relationship of some sort and the child has a reference to its parent, something like this

我认为如果类和它的子类共享某种类型的子父关系并且子类引用它的父类,就会发生这种情况,就像这样

public interface Node
{   
    String getName();

    int getValue();

    Container getParentContainer();
}

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

I would be interested to see how this can be designed in a better way to resolve this.

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