为什么一个superclass可以初始化为Java中的一个childclass?

Why can a super class be initialized as a child class in Java?

简而言之,这如何以及为什么可能:

Object obj=new MyClass();

Object 是所有 objects 的超级 class,因此 MyClass 是 Object 的 child class。一般来说,在Java,为什么可以在parentclass中使用childclass的构造函数?


我明白它怎么可能反过来,因为 child 拥有 parent class 的所有 variables/methods,所以当你初始化它们时你只是初始化 parent 构造函数中指定的变量,这些变量根据定义存在于 child 中。问题是,当你反过来时,它不一定是真的。 A child 可以有 parent 没有的变量 ,那么如何将 child 构造函数与 parent 一起使用,当 parent 一开始甚至没有变量时?


这个特性在开发中有什么用?我想如果你想要一个class B的实例,你会把它声明为B thing=new B(),而不是 A thing=new B()。这可能是我缺乏经验的谈话,所以我很感激关于为什么以及如何将 parent class 初始化为它的 children.

之一的启示

因为MyClassObject。请注意,java 是特殊的,因为 Object 是所有其他 class 类型的超 class(在 C++ 中没有等效项)。

一个更有趣的例子是,如果你有一个 class 或接口和一个或多个子 class 。这在 OOD 中经常出现。以 java 的 jdbc API 为例:一组用于连接和查询数据库的通用接口,可以由不同的具体 classes 实现。您只需要编写 API 代码,然后在运行时使用您选择的数据库的实现。

http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html

Class 对象是 class 层次结构的根。每个 class 都有 Object 作为一个 superclass。所有的对象,包括数组,都实现了这个class.

的方法

每个 Java class 都是一个Object。这就是为什么。

http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

在 java.lang 包中定义的对象 class 定义并实现了 所有 classes 共有的行为——包括您编写的行为。在Java平台中,很多class直接派生自Object,其他class派生自其中一些class,依此类推,形成了[=的层次结构34=]es.

这里有两个不同的东西:

  • 新建实例
  • 将该实例分配给 一个变量

由于您的 MyClass 实例也是 Object 的实例,因此效果很好。

考虑以下一般情况:

class A extends B implements C,D {
}

因为你的A是一个B,也是一个C,一个D和一个Object,一旦你创建了一个实例,你可以(直接或间接)将其分配给所有这些类型的变量:

A a = new A();
B b = a;
C c = a;
D d = a;
Object o = a;

您在字段或方法上的视图受限于变量的类型(即作为 C 类型的变量,您只能请参阅 C) 声明的方法。 尽管如此,您的实例始终是您使用构造函数实例化的类型,无论变量类型如何。

您正在考虑 C++ 语义,但这是 Java。在 Java 中,所有非基本类型变量都是引用,而不是实例。

在 C++ 中,当你说

Object obj;

您在堆栈或静态内存中分配了一个新的 Object 实例。

当你说

Object obj = new MyObject;

您调用 Object class 的构造函数,它采用 MyObject 指针(或者可能是 MyObject 可以转换成的其他东西)。

在Java、

Object obj;

不会创建 Object 的任何实例。它只是创建一个可以引用 Object 实例的变量,但目前不引用任何实例。初始化为null.

Object obj = new MyObject();

分配 MyObject 的一个实例。它不会分配 Object 的新实例。它只是将变量设置为引用新实例。在 C++ 术语中,这更类似于

Object *obj = new MyObject();

所以我们不是从子实例构造父实例。我们正在将变量设置的值从 null 更改为新的子实例。

Why is it possible to use the constructor of a child class in the parent class?

这是不正确的。当你这样做时

Object obj = new MyClass();

Object obj; 声明类型 Object 的引用 和 new MyClass(); returns 对其创建的对象的引用。

因此,您正在实例化一个 MyClass 并将对创建的对象的引用分配给类型 Object 的引用,这是可能的,因为 MyClass 是一个 Object.

正如你所说,

A child can have variables the parent doesn't

这称为扩展父功能 (inheritance)。

对于你的第二个问题,想想 classic Animal 的例子:假设你创建了一个 Animal class 并且你创建了一个方法 makeSound()它。

现在您创建了 AnimalDogCat 的两个子classes,它们覆盖了 AnimalmakeSound() 方法(Dog 吠声和 Cat 喵喵声)。

想象一下,您使用 List 代表一个满是 Animal 人(Dog 人和 Cat 人)的房间,并且您想要制作所有这些人makeSound()。您的列表将被声明为 List<Animal>,因为您不知道要存储的 Animal 的种类。

然后迭代 List 为每个 Animal 调用 makeSound()AnimalDog 还是 Cat 都没关系,它会发出声音。

然后假设您想将 Bird 添加到 List。很简单,不是吗?

Java 中的每个 class 都是 Object 的后代。所以根据定义,MyClass 是一个 Object,但是它的一个更特殊的版本。可以这样想:每个生物都是一个AnimalCat是一种特殊的动物;特定类型。由于 CatAnimal,您仍然可以将其称为 Animal:

Animal a = new Cat();

但是这样做,使用 a,你不能做任何特定于 Cat 的事情,比如 meow()purr(),但你可以调用方法对所有 Animal 都有效,例如 breathe().

HTH

首先要对事物有一个清晰的认识。您的示例表达式: Object obj = new MyClass();实际上是两个基本运算的复合。

第一个是创建 MyClass 的实例:new MyClass()new 关键字基本上是实际获取 class 实例的唯一方法(让我们忽略运行时反射以保持简单),并且您实际上是在此处命名要创建的内容 (MyClass)它的构造函数。除了您用 new 关键字字面上命名的内容之外,没有办法创建任何其他内容。 new 的结果(隐含地)是 MyClass 的实例,但是 new X 的显式结果是类型 Xreference(引用引用新创建的实例)。

现在第二个操作是将对您的(新)MyObject 的引用分配给另一个对象类型的引用。这是有效的,因为 MyObject 一个对象(由于继承)。

为什么需要这个?

这是一个 必不可少的 功能,可以实际利用 多态性 。将任何子 class 称为其父 class 的能力使多态性如此 强大 。您基本上会在两个 class 有相同方面但也有差异的地方使用它。

一个现实世界的例子是图形用户界面。 window 中有按钮、列表、表格和面板,它们都是用户界面元素,但每个元素都做不同的事情。为了将它们整齐地组织在 window 中,这些元素通常嵌套在面板中,更抽象地说是 容器 。现在,容器不关心将何种元素放入其中,只要它们是组件即可。但是要正确处理它们,容器 确实 需要有关这些组件的一些基本信息,主要是它们占据了多少 space 以及如何实际绘制它们。所以这被建模为:

public abstract class Component {
    public int getWidth() { ... }

    public int getHeight() { ... }

    public void paint(Graphics g) { ... }
}

public class Container extends Component {
    public void add(Component child) { ... }

    public void paint(Graphics g) {
        for (Component child : children) {
            child.paint(g);
        }
    }
}

这几乎是直接从 JDK 中提取出来的,关键是,如果您需要将每个组件作为其具体类型进行引用,那么构建容器是不切实际的,它需要额外的代码来您决定制作的每个组件(例如,会有一个 addButton、addTable 等)。因此,Container 只是参照 Component 工作。无论创建什么组件(例如 Button、CheckBox、RadioButton 等),由于 Container 仅依赖它们来处理所有 be 组件,它可以处理它们。

class myMobile{
  public void call{
     System.out.println("Mobile");
      }
  }
    public class mainClass{
        public static void main(){
            Object o=new myMobile();
                //here we can call methods which are common to all 
                                     // objects not specific to 
                                                   // myMobile object
           }
  }