JAVA基础篇(5)——【多态中的向上转型和向下转型】

(1)向上转型:

将子类对象转化为父类对象,通俗来说个人理解就是,就是通过父类对象执行子类对象中的方法等。

例子:

//父类
public class Transtation1 {
	public void animal(){
		System.out.println("在这里我还是动物");
	}
}
//子类
public class Transtation2 extends Transtation1 {
	
	public void animal(){
		System.out.println("在这里我已经不是动物了");
	}
	public void bird(){
		System.out.println("我是一只鸟");
	}
	
	public void cat(){
		System.out.println("我是一只猫");
	}
	public void dog(){
		System.out.println("我是一条狗");
	}
}
//测试类
public class TranstationTest {

	public static void main(String[] args) {		
		//向上转型
		Transtation1 a = new Transtation2();
		a.animal();
	    //需要注意的是向上转型时a会遗失除与父类对象共有的其他方法
	    //如a.bird() 这是不允许的,无法通过编译。虽然a指向了子类对象Transtation2,但是只能访问子类中与父类相同的方法。		
	}
}

输出结果:在这里我已经不是动物了

重点注意:向上转型的对象,只能访问子类中的与父类相同的方法,其他方法丢失。例如本例中,只能有a.animal()不能有a.bird(),即不能有子类的其他方法。

向上转型的好处:可以减少代码冗余。重新来一个猫和狗的例子,如下:

//父类
public class animail {
	public void eat(){
		System.out.println("我还不知道吃啥...");
	}
}
//子类1
public class cat extends animail {
	public void eat(){
		System.out.println("我吃鱼");
	}
}
//子类2
public class dog extends animail {
	public void eat(){
		System.out.println("我吃骨头");
	}
}

使用了向上转型的测试类: 


//测试类  使用了向上转型的测试类
public class Test {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		animail c= new cat();
		animail d =new dog();
		eat(c);
		eat(d);
	}
    //只需写一个方法
	public static void eat(animail a){
		a.eat();		
	}
}

未使用向上转型的测试类:

//测试类 未使用向上转型  这是不好的方式
public class Test {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		cat c = new cat();
		dog d = new dog();
		eat(c);
		eat(d);
	}
	//不用向上转型,就得写两个方法
	public static void eat(cat a){
		a.eat();		
	}
	public static void eat(dog a){
		a.eat();		
	}
}

 两个测试类的输出结果都为:

我吃鱼
我吃骨头

两个测试类中的区别在哪里:虽然都达到了一样的效果,但是代码实现不一样,在使用了向上转型的类中,我们只需要写一次eat(animal   a)方法,其中的参数是父类animal a,在每次增加一个动物的时候,我们无需再写eat()方法。但是。如过按照测试类2,每增加一个动物都要多写一次eat()方法,之多一个好说,那突然多了10000种动物呢?结果不言而喻。

(2)向下转型:

向下转型通俗来讲就是把父类对象转化为子类对象:

例如:更改测试类中的代码为如下代码

1)安全的向下转型

//测试类
public class TranstationTest {

	public static void main(String[] args) {		
		//向上转型
		Transtation1 a = new Transtation2();
		a.animal();
	    //需要注意的是向上转型时a会遗失除与父类对象共有的其他方法
	    //如a.bird() 这是不允许的,无法通过编译。虽然a指向了子类对象Transtation2,但是只能访问子类中与父类相同的方法。
		
		//安全的向下转型
		Transtation2 b = (Transtation2) a;
		b.animal();
		b.bird();
	}
}

输出结果:

在这里我已经不是动物了
在这里我已经不是动物了
我是一只鸟

2)不安全的向下转型

//测试类
public class TranstationTest {

	public static void main(String[] args) {		

		//不安全的向下转型,并以不会报错,但执行时报错
		Transtation1 c = new Transtation1();
		Transtation2 d = (Transtation2) c;
		d.animal();
		d.bird();
	}
}

运行报错:Exception in thread "main" java.lang.ClassCastException: com.test.zy726.Transtation1 cannot be cast to com.test.zy726.Transtation2
    at com.test.zy726.TranstationTest.main(TranstationTest.java:18)

是不是依旧不怎么懂,那来个更加形象的例子,还是前面猫和狗的例子,这是他们的一个测试类:

//测试1
public class TestDogAndCat {
	public static void main(String[] args) {
	//先向上转型,再向下转型
	animail a =new cat();
	cat c = (cat) a;
	c.eat();
}

//执行结果是:我吃鱼
//测试2
public class TestDogAndCat {
	public static void main(String[] args) {
	//先向上转型再向下
	animail a =new cat();
	dog d = (dog) a;
	d.eat();	
	}
}
//执行结果是啥?你以为会是:我吃骨头吗?当然不是
//它是无法执行的
//报错异常:Exception in thread "main" java.lang.ClassCastException: com.test.zy726.cat cannot be cast to com.test.zy726.dog
	at com.test.zy726.TestDogAndCat.main(TestDogAndCat.java:11)

分析:为啥测试1可以,测试2就不行了?因为,a本来就已经是个猫的对象了,你在测试2里面你想把它变成狗吗?

public class TestDogAndCat {
	public static void main(String[] args) {
	//向上转型
	animail a =new animail();
	dog d = (dog) a;
	d.eat();
	}
}
//这样可以吗?不可以
//运行结果,抛出异常:Exception in thread "main" java.lang.ClassCastException: com.test.zy726.animail cannot be cast to com.test.zy726.dog
	at com.test.zy726.TestDogAndCat.main(TestDogAndCat.java:11)

分析:为啥呢,你去考古发现了一个几千年前的动物,你就能直接说,哦,这个动物是狗?

向下转型总结:

(a)向下转型的前提是父类对象指向的是子类对象(也就是说,在向下转型之前,它得先向上转型)

(b)向下转型只能转型为本类对象(猫是不能变成狗的)。

猜你喜欢

转载自blog.csdn.net/qq_39077728/article/details/81222036
今日推荐