java上转型对象详解
class Father {
String Fname = "爸爸";
public void sleep() {
//睡觉方法
System.out.println(Fname + "睡觉");
}
}
class Son extends Father {
String Sname = "儿子";
public void p() {
//调皮方法
System.out.println(Sname + "调皮");
}
}
public class Test {
public static void main(String[] args) {
Father f= new Son();
f.sleep();
System.out.println(f.Fname);
//System.out.println(f.Sname); 编译器报错
//f.p(); 编译器报错
System.out.println();
System.out.println(((Son)f).Fname);
System.out.println(((Son)f).Sname);
((Son)f).sleep();
((Son)f).p();;
}
}
//程序输出结果为
// 爸爸睡觉
// 爸爸
//
// 爸爸
// 儿子
// 爸爸睡觉
// 儿子调皮
当一个父类的对象引用的是子类的实例时,我们可以把这个父类对象叫做上转型对象。
这里有两种方法创建上转型对象
1.Father f= new Son();
2.Son son= new Son();
Father f=(Father)son;
Son是Father的子类,f就是上转型对象
(1)上转型对象不能操作子类声明定义的成员变量(失掉了这部分属性),不能使用子类声明定义的方法(失掉了一些功能)。这里f失去了Sname这个成员变量,失去了P这个方法,可以看作是一种”瘦身”。
(2)上转型对象可以访问子类继承或隐藏的成员变量,也可以调用子类继承的方法或子类重写的实例方法
(3)可以将上转型对象再强制转换成子类对象,这样,该子类对象又具备了子类具有所有属性和方法。
(4)如果子类重写了父类的某个方法后,当对象的上转型对象调用这个方法时一定是调用了这个重写的方法。这里我们再展开来讲一下,我们给Father类和Son类分别添加speak方法
class Father {
String Fname = "爸爸";
public void sleep() {
//睡觉方法
System.out.println(Fname + "睡觉");
}
public void speak() {
System.out.println("我是爸爸");
}
}
class Son extends Father {
String Sname = "儿子";
public void p() {
//调皮方法
System.out.println(Sname + "调皮");
}
public void speak() {
System.out.println("我是儿子");
}
}
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Father f= new Son();
f.speak();
//调用子类重写的方法
System.out.println();
((Son)f).speak();
}
}
//程序输出结果为:
// 我是儿子
//
// 我是儿子
Son重写了Father类的speak方法,上转型对象调用的是son类的speak方法,所以输出”我是儿子”。
接下来,我们就需要了解上转型对象的实现意义,为什么 java开发人员要设计一个上转型对象呢。
class Animal {
void cry() {
}
}
class Dog extends Animal {
void cry() {
System.out.println("汪汪");
}
}
class Cat extends Animal {
void cry() {
System.out.println("喵喵");
}
}
public class 上转型对象多态 {
public static void beat(Dog dog) {
System.out.println("打了它一下");
dog.cry();
}
public static void beat(Cat cat) {
System.out.println("打了它一下");
cat.cry();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Dog dog= new Dog();
Cat cat= new Cat();
beat(dog);
beat(cat);
}
}
//程序输出结果:
// 打了它一下
// 汪汪
// 打了它一下
// 喵喵
这里我们没有使用上转型对象,beat方法写了两种。
public class 上转型对象多态 {
public static void beat(Animal animal) {
System.out.println("打了它一下");
animal.cry();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Dog dog= new Dog();
Cat cat= new Cat();
beat(dog);
beat(cat);
}
}
//程序输出结果:
// 打了它一下
// 汪汪
// 打了它一下
// 喵喵
原来需要写两个beat函数才能实现的功能,现在只需写一个就行了
我们使用了上转型对象,上转型对象调用子类重写的方法,实现了方法的多态,还降低了程序之间关联性。
比如说我现在想要再写一个Animal类的子类,如果不用上转型对象,那我还要再添加一个beat方法,但是有了上转型对象,Animal的子类想怎么添加,怎么添加,beat方法到最后都可以使用。
同时,我们还注意到,上转型对象会调用子类重写的方法,父类隐藏的那个方法永远都用不到。上面的例子中Cat和Dog重写了Animal的cry()方法,Animal中的cry()的方法体是什么根本无所谓。Java开发人员想了想,反正隐藏的方法体是什么无所谓,要不我们直接定义一个结构,方法只可以声明(没有方法体)。于是这样,抽象类就被发明了。后来,由于java只支持单继承,抽象类有时不能满足开发需求,开发人员又发明了接口,接口可以实现多重继承,一个类可以实现多个接口。
面向对象编程,代码多态和复用的思想贯串始终。这种编程思想真的非常好,极大的降低了程序之间的关联性
==============================================================================
参考博客:
Java向上转型和向下转型的通俗简单理解以及使用用途
Java向上转型的作用(有详细代码介绍)
这边还有一个解释抽象类和接口区别的深度好文,大家也可以看看:
Java 接口(interface)的用途和好处