我问一个很简单的问题,但我对这个有点糊涂了。
假设我有一类Parent
:
public class Parent {
int name;
}
而有另一个类Child.java
:
public class Child extends Parent{
int salary;
}
最后我Main.java类
public class Main {
public static void main(String[] args)
{
Parent parent = new Child();
parent.name= "abcd";
}
}
如果我让孩子喜欢的对象
Child child = new Child():
然后, child
对象可以访问这两个name and salary
的变量。
我的问题是:
Parent parent = new Child();
仅给出的接入name
父类的变量。 那么,什么是这一行的确切用途?
Parent parent = new Child();
而且当它被使用动态多态性那么为什么子类的变量不是这样做之后访问
Parent parent = new Child();
Answer 1:
首先,阐明术语:我们正在分配Child
对象类型的变量Parent
。 Parent
是恰好是的子类型的对象的引用Parent
,一个Child
。
它在一个更复杂的例子是唯一有用的。 想象一下,你添加getEmployeeDetails
到类家长:
public String getEmployeeDetails() {
return "Name: " + name;
}
我们可以覆盖该方法在Child
提供更多的细节:
@Override
public String getEmployeeDetails() {
return "Name: " + name + " Salary: " + salary;
}
现在,您可以编写代码,获取任何信息是可用的,对象是一个行Parent
或Child
:
parent.getEmployeeDetails();
下面的代码:
Parent parent = new Parent();
parent.name = 1;
Child child = new Child();
child.name = 2;
child.salary = 2000;
Parent[] employees = new Parent[] { parent, child };
for (Parent employee : employees) {
employee.getEmployeeDetails();
}
将导致输出:
Name: 1
Name: 2 Salary: 2000
我们用一个Child
的Parent
。 它进行了专门的行为所特有的Child
类的,但是当我们叫getEmployeeDetails()
我们可以忽略的差异,集中讨论如何Parent
和Child
都差不多。 这就是所谓的亚型多态性 。
更新后的问题问为什么Child.salary
时不能访问Child
对象存储在一个Parent
参考。 答案是“多态”和“静态类型”的交叉点。 因为Java是在编译时静态类型你从编译器的某些保证,但你不得不遵守规则,以换取或代码将无法编译。 在此,相关担保是一个亚型(例如每个实例Child
)可以作为它的超类型(如实例Parent
)。 例如,可以保证的是,当你访问employee.getEmployeeDetails
或employee.name
方法或字段是可分配给一个变量的任何非空对象上定义employee
类型的Parent
。 为了使这一保证,编译器只考虑静态类型(基本的变量引用的类型, Parent
)决定时,你可以访问什么。 所以你不能访问在运行时类型的对象,所规定的任何成员Child
。
如果你真的想用一个Child
的Parent
,这是一个简单的限制相处,你的代码将是可用的Parent
及其所有亚型。 时是不能接受的,使所述基准的类型Child
。
Answer 2:
它可以让你通过一个共同的父界面访问所有子类。 这是上运行所有子类可用常见的操作是有益的。 需要一个更好的例子:
public class Shape
{
private int x, y;
public void draw();
}
public class Rectangle extends Shape
{
public void draw();
public void doRectangleAction();
}
现在,如果您有:
List<Shape> myShapes = new ArrayList<Shape>();
您可以在列表中引用的每个项目的形状,你不必担心,如果它是一个矩形或一些其他类型的像我们说圆。 你可以把它们都一样; 你可以借鉴他们。 你不能叫doRectangleAction,因为你不知道的造型真是一个矩形。
这是一个行业的您在一个通用的方式治疗对象和具体治疗之间。
真的,我认为你需要阅读更多有关OOP。 一本好书应该有所帮助: http://www.amazon.com/Design-Patterns-Explained-Perspective-Object-Oriented/dp/0201715945
Answer 3:
如果您分配父类的子类,这意味着你使用的父类的共同特征一致。
它可以让你从不同的子类实现的自由,抽象的。 其结果是限制了你的父特征。
然而,这种分配被称为向上转型。
Parent parent = new Child();
相反被向下转换。
Child child = (Child)parent;
所以,如果你创建的实例Child
和其向下转换到Parent
,您可以使用该类型的属性name
。 如果创建的实例Parent
,你可以做同样与前一种情况,但你不能用salary
,因为不是在这样的属性Parent
。 返回到可以使用以前的情况下salary
,但只有当向下转型到Child
。
还有更详细的解释
Answer 4:
这很简单。
Parent parent = new Child();
在这种情况下,对象的类型是Parent
。 蚂蚁Parent
只有一个属性。 它的name
。
Child child = new Child();
在这种情况下该对象的类型是Child
。 蚂蚁Child
有两个属性。 他们name
和salary
。
事实是,有没有必要在声明立即初始化非最终场。 通常这才是在运行时进行,因为往往你可以不完全准确地实施,将你需要知道的东西。 例如假设你有一个类层次结构与类Transport
的头。 和三个子类: Car
, Helicopter
和Boat
。 还有的另一个类Tour
其中有场Transport
。 那是:
class Tour {
Transport transport;
}
只要一个用户没有进行过预订的行程,也没有选择的传输特定类型的,你不能初始化这个领域。 这是第一个。
其次,假设所有这些类必须有一个方法go()
但有不同的实现。 您可以定义默认的超基本实现Transport
,并拥有在每个子类唯一的实现。 有了这个初始化Transport tran; tran = new Car();
Transport tran; tran = new Car();
你可以调用方法tran.go()
并获得结果,而不必担心具体实施。 它会调用overrided从特定的子方法。
此外,您可以在使用超类的实例比比皆是使用子类的实例。 例如你要提供机会,以租你的运输。 如果你不使用多态,你必须写很多的每种情况的方法: rentCar(Car car)
, rentBoat(Boat boat)
等等。 与此同时多态性允许您创建一个通用的方法rent(Transport transport)
。 您可以在任何的子类的对象是经过Transport
。 此外,如果一段时间内的逻辑将高达增加,你需要创建层次结构中的另一个类? 当使用多态,你不需要改变任何东西。 只是扩展类Transport
,并通过新类进入方法:
public class Airplane extends Transport {
//implementation
}
与rent(new Airplane())
而new Airplane().go()
在第二个案例。
Answer 5:
当您编译程序的基类的引用变量获取内存和编译器检查在类的所有方法。 因此,检查所有的基类的方法,但不是子类的方法。 现在,在运行时创建对象时,只检查方法可以运行。 如果一个方法在子类函数运行覆盖。 儿童类的其他功能无法运行,因为编译器并没有在编译时认出了他们。
Answer 6:
当你有几个实现这种情况发生。 让我解释。 Supppose你有几个排序算法,你想在运行时选择一个来实现,或者你想给别人增添自己的执行能力。 为了解决这个问题,你通常会创建一个抽象类(家长),并有不同的实现(儿童)。 如果你写的:
Child c = new Child();
您绑定您的实现儿童类,你不能再改变它。 否则,如果你使用:
Parent p = new Child();
只要孩子伸出家长可以不用修改代码在将来改变它。
同样的事情可以使用接口来实现:家长已不再一类,但一个Java接口。
一般来说,你可以,你想有几个DB依赖实现在DAO模式使用此计算策略。 你可以给看看FactoryPatter或AbstractFactory模式。 希望这可以帮到你。
Answer 7:
比方说,你想有父类的实例数组,和一组子类Child1,CHILD2,Child3延长家长。 当你只与父类的实现,这是更普遍的兴趣,不关心的子类引入了更多具体的东西有很的情况。
Answer 8:
声明父父,所以Java将只提供方法和父类的属性。
Child child = new Child();
应该管用。 要么
Parent child = new Child();
((Child)child).salary = 1;
文章来源: Why do we assign a parent reference to the child object in Java?