简而言之,这是如何以及为何可能:
Object obj=new MyClass();
Object是所有对象的超类,因此MyClass是Object的子类。通常,在Java中,为什么可以在父类中使用子类的构造函数?
我理解它是如何反过来的,因为子类具有父类的所有变量/方法,所以当你初始化它们时,你只是初始化在父构造函数中指定的变量,它们按照定义存在孩子问题是,当你走另一条路时,它不一定是真的。 子项可以包含父项的变量,那么如果父项甚至没有变量,那么如何将子构造函数与父项一起使用呢?
此功能在开发中有什么用途?我认为如果你想要一个B类实例,你会把它声明为B thing = new B(),而不是A thing =新B()。这可能是我缺乏经验的谈话,所以我会很感激为什么以及如何将父类初始化为其子女之一的启示。
答案 0 :(得分:7)
为什么可以使用子类的构造函数 父母班?
这不正确。当你这样做
Object obj = new MyClass();
Object obj;
声明Object
类型的引用
并且new MyClass();
返回对其创建的对象的引用。
因此,您要实例化MyClass
并将对创建的对象的引用分配给Object
类型的引用,这是可能的,因为MyClass
是Object
}。
正如你所说,
孩子可以拥有父母没有的变量
这称为扩展父功能(inheritance)。
对于您的第二个问题,请考虑经典的Animal
示例:假设您创建了一个Animal
类,并在其上创建了一个方法makeSound()
。
现在您创建两个Animal
,Dog
和Cat
的子类,它们会覆盖makeSound()
的{{1}}方法(Animal
咆哮和Dog
喵喵叫。
想象一下,您使用Cat
代表一个充满Animal
s(Dog
s和Cat
s)的房间,并且您想要制作所有这些房间{{ 1}}。您的列表将被声明为List
,因为您不知道将要存储的makeSound()
种类。
然后,您遍历List<Animal>
为每个Animal
致电List
。 makeSound()
是Animal
还是Animal
并不重要,它会发出声音。
然后想象你想将Dog
添加到Cat
。容易,不是吗?
答案 1 :(得分:2)
您正在考虑C ++语义,但这是Java。在Java中,所有非基本类型变量都是引用,而不是实例。
在C ++中,当你说
时Object obj;
在堆栈或静态内存中分配新的Object
实例。
当你说
时Object obj = new MyObject;
你调用一个Object
类的构造函数,它带有MyObject
指针(或者可能是MyObject可以转换成的其他东西)。
在Java中,
Object obj;
不会创建Object
的任何实例。它只是创建一个可以引用Object
实例的变量,但此刻并不引用任何实例。它被初始化为null
。
Object obj = new MyObject();
分配MyObject
的实例。它不会分配Object
的新实例。它只是设置变量以引用新实例。在C ++术语中,这与
Object *obj = new MyObject();
因此我们不会从子实例构建父实例。我们正在将变量设置的值从null更改为新的子实例。
答案 2 :(得分:2)
首先,你必须清楚地了解事物。你的示例表达式:
Object obj = new MyClass();
实际上是两个基本操作的复合。
第一个是创建MyClass的实例:new MyClass()
。 new
关键字基本上是实际获取类实例的唯一方法(让忽略运行时反射以保持这个简单),并且您实际上通过其构造函数命名您要创建的内容(MyClass)。除了使用new关键字命名的内容之外,无法创建任何其他内容。 new的结果是(隐式)MyClass的一个实例,但new X
的显式结果是X
类型的引用(引用引用新创建的实例) )。
现在第二个操作是将对(new)MyObject的引用分配给另一个Object类型的引用。这是有效的,因为MyObject 是一个对象(由于继承)。
你为什么需要这个?
这是实际使用多态的基本功能。将任何子类作为其超类引用的能力使得多态性如此强大。你基本上会在两个类共有一个方面的地方使用它,但也存在差异。
现实世界的例子是图形用户界面。窗口中有按钮,列表,表格和面板,它们都是用户界面元素,但每个元素都有不同的含义。为了在窗口中整齐地呈现它们,这些元素通常嵌套在面板中,更抽象地说是容器。现在,只要它们是组件,容器就不关心它是什么类型的元素。但要正确处理它们,容器 需要一些关于这些组件的基本信息,主要是它们占用了多少空间以及如何实际绘制它们。所以这被建模为:
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中解脱出来的,重点是,如果你需要将每个Component称为具体类型,那么构建一个Container是不切实际的,你需要为你决定制作的每个Component提供额外的代码。 (例如,会有addButton,addTable等)。所以相反,Container只是参考Component。无论创建什么组件(例如Button,CheckBox,RadioButton等),由于Container只依赖于所有是组件,它可以处理它们。
答案 3 :(得分:1)
Java中的每个类都来自Object
。因此,根据定义,MyClass
是Object
,但它是一个更专业的版本。可以这样想:每个生物都是Animal
。 Cat
是一种特殊的动物;特定类型。由于Cat
是Animal
,您仍然可以将其称为Animal
:
Animal a = new Cat();
但是,使用a
这样做,您无法对Cat
执行任何特定操作,例如meow()
或purr()
,但您可以调用哪些方法适用于所有Animal
,例如breathe()
。
HTH
答案 4 :(得分:1)
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
}
}
答案 5 :(得分:0)
因为MyClass
是 Object
。请注意,java是特殊的,因为Object
是每个其他类类型的超类(在C ++中没有等价物)。
更有趣的例子是,如果您有一个类或接口以及一个或多个子类。这在OOD中一直出现。考虑例如java的jdbc API:一组通用的接口,用于连接和查询可由不同具体类实现的数据库。您只需要对API进行编码,然后在运行时使用所选数据库的实现。
答案 6 :(得分:0)
http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html
Class Object是类层次结构的根。每个类都有Object作为超类。所有对象(包括数组)都实现此类的方法。
即。 每个 Java类都是Object
。这就是原因。
http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
在java.lang包中定义的Object类定义并实现所有类(包括您编写的)的通用行为。在Java平台中,许多类直接从Object派生,其他类派生自其中一些类,依此类推,形成类的层次结构。
答案 7 :(得分:0)
这里有两个不同的东西:
由于您的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;
字段或方法上的视图受变量类型的限制(i.E.作为C类型的变量,您只能看到C声明的方法)。 尽管如此,无论变量类型如何,您的实例始终都是使用构造函数实例化的类型。