为什么一个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.
之一的启示
因为MyClass
是Object
。请注意,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()
它。
现在您创建了 Animal
、Dog
和 Cat
的两个子classes,它们覆盖了 Animal
的 makeSound()
方法(Dog
吠声和 Cat
喵喵声)。
想象一下,您使用 List
代表一个满是 Animal
人(Dog
人和 Cat
人)的房间,并且您想要制作所有这些人makeSound()
。您的列表将被声明为 List<Animal>
,因为您不知道要存储的 Animal
的种类。
然后迭代 List
为每个 Animal
调用 makeSound()
。 Animal
是 Dog
还是 Cat
都没关系,它会发出声音。
然后假设您想将 Bird
添加到 List
。很简单,不是吗?
Java 中的每个 class 都是 Object
的后代。所以根据定义,MyClass
是一个 Object
,但是它的一个更特殊的版本。可以这样想:每个生物都是一个Animal
。 Cat
是一种特殊的动物;特定类型。由于 Cat
是 Animal
,您仍然可以将其称为 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
的显式结果是类型 X
的 reference(引用引用新创建的实例)。
现在第二个操作是将对您的(新)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
}
}
简而言之,这如何以及为什么可能:
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.
之一的启示因为MyClass
是Object
。请注意,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()
它。
现在您创建了 Animal
、Dog
和 Cat
的两个子classes,它们覆盖了 Animal
的 makeSound()
方法(Dog
吠声和 Cat
喵喵声)。
想象一下,您使用 List
代表一个满是 Animal
人(Dog
人和 Cat
人)的房间,并且您想要制作所有这些人makeSound()
。您的列表将被声明为 List<Animal>
,因为您不知道要存储的 Animal
的种类。
然后迭代 List
为每个 Animal
调用 makeSound()
。 Animal
是 Dog
还是 Cat
都没关系,它会发出声音。
然后假设您想将 Bird
添加到 List
。很简单,不是吗?
Java 中的每个 class 都是 Object
的后代。所以根据定义,MyClass
是一个 Object
,但是它的一个更特殊的版本。可以这样想:每个生物都是一个Animal
。 Cat
是一种特殊的动物;特定类型。由于 Cat
是 Animal
,您仍然可以将其称为 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
的显式结果是类型 X
的 reference(引用引用新创建的实例)。
现在第二个操作是将对您的(新)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
}
}