向上、向下转型

向上、向下转型

基础知识多肽回顾:
1.多肽是方法的多肽,不是属性的多肽(多肽与属性无关)。
2.多肽的存在有三个必要条件:继承、方法重写、父类引用指向子类对象。
3.父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多肽就出现了。

一、向上转型

原文链接

class Animal {
	public void eat(){
		System.out.println("父类的 吃...");
	}
}
class Bird extends Animal{	
	@Override
	public void eat(){
		System.out.println("子类重写的父类的  吃吃吃...");
	}	
	public void fly(){
		System.out.println("子类新方法  飞飞飞...");
	}
}
public class Sys{
	public static void main(String[] args) {
		Animal b=new Bird(); //向上转型
		b.eat(); 
		//  b.fly(); b虽指向子类对象,但此时子类作为向上的代价丢失和父类不同的fly()方法
		sleep(new Male());
		sleep(new Female());//传入的参数是子类-----!!
	}
	
	public static void sleep(Human h) {//方法的参数是父类------!!!
 		 h.sleep();
        }
}     
public class Human {
	public void sleep() {
		System.out.println("父类人类   sleep..");
	}
}
class Male extends Human{
	@Override
	public void sleep() {
		System.out.println("男人 sleep..");
	}
}
class Female extends Human {
	@Override
	public void sleep(){
		System.out.println("女人 sleep..");
	}
}

输出:
子类重写的父类的 吃吃吃…
男人 sleep…
女人 sleep…
详解:

  1. 向上转型的实现

        Animal b=new Bird(); //向上转型
        b.eat(); // 调用的是子类的eat()方法
        b.fly(); // 报错!!!!!-------b虽指向子类对象,但此
        时子类作为向上转型的代价丢失和父类不同的fly()方法------
    

2.为何不直接Bird b=new Bird();b.eat() 呢?

这样就没有体现出面向对象的抽象的编程思想呀,降低了代码的可扩展性.

3.向上转型的好处?

       sleep(new Male());//调用方法时传入的参数是子类
       sleep(new Female());

         public static void sleep(Human h) //方法的参数是父类

        {

         h.sleep();

         }

如上代码就是用的向上转型,若是不用向上转型,那么有多少个子类就得在这儿写多少种不同的睡觉方法~~~~~~

说到这里是不是还是感觉云里雾里,再上个例子
Person 可以表示为一个抽象的东西就是人。比如说人可以唱歌, 就好比Person类中有一个sing方法.
那么这个抽象的类(Person 人)可以具体到两类或者更多类 比如 男人,女人 。
Man extends Person 或者 Woman extends Person
那么男人 还有 女人 分别实现sing方法。 因为男人和女人唱歌总还是有区别的嘛。

当 Person p = new Man(); p.sing(); 这个时候就是调用男人唱歌的sing方法
当 Person p = new Woman(); p.sing(); 这个时候就是调用女人的唱歌的sing方法

这样其实就是一个java的继承,多态. 利于程序扩展. 你需要理解这种设计方式,会让你写出更易维护简洁的代码。

二、向下转型

class Fruit{
	public void myName(){
		System.out.println("我是父类  水果...");
	}
}
 
class Apple extends Fruit{ 
	@Override
	public void myName() { 
		System.out.println("我是子类  苹果...");
	}
	public void myMore(){
		System.out.println("我是你的小呀小苹果~~~~~~");
	}
}
 
public class Sys{ 
	public static void main(String[] args) { 
		Fruit a=new Apple(); //向上转型
		a.myName();
		
		Apple aa=(Apple)a; //向下转型,编译和运行皆不会出错(正确的)
		aa.myName();//向下转型时调用的是子类的
		aa.myMore();;
		  
		Fruit f=new Fruit();
        Apple aaa=(Apple)f; //-不安全的---向下转型,编译无错但会运行会出错
  		aaa.myName();
  		aaa.myMore(); 
	}
}

输出:
我是子类 苹果…
我是子类 苹果…
我是你的小呀小苹果~~~~~~
Exception in thread “main” java.lang.ClassCastException: com.sheepmu.Fruit cannot be cast to com.sheepmu.Apple
at com.sheepmu.Sys.main(Sys.java:30)

由此得到向下转型的意义:父类引用可以使用子类的新增方法
详解:

1.正确的向下转型

                Fruit a=new Apple(); //向上转型
                a.myName(); 
                Apple aa=(Apple)a; //向下转型,编译和运行皆不会出错(正确的)
                aa.myName();
                aa.myMore();

a指向子类的对象,所以子类的实例aa也可以指向a啊~~

向下转型后因为都是指向子类对象,所以调用的当然全是子类的方法~~

2.不安全的向下转型

           Fruit f=new Fruit();
           Apple aaa=(Apple)f; //-不安全的---向下转型,编译无错但会运行会出错
           aaa.myName();
           aaa.myMore(); 

f是父类对象,子类的实例aaa肯定不能指向父类f啊~~~

3.Java为了解决不安全的向下转型问题,引入泛型的概念

4.为了安全的类型转换,最好先用 if(A instanceof B) 判断一下下

这里引出一个问题:JAVA的面向对象应该怎样理解。(之前就突然被一个面试问到对面向对象、面向过程的理解)有很多种答案,这里是B站上看到的一个老师讲的。

所有的程序其实只有三个核心元件:变量、选择语句、循环语句。
面向过程变成:我们可以通过方法,来把这三个东西放在一起。然后通过方法一方法二串联起来,最终形成一个程序。
面向对象:对象,它是一个更高级的组织方式。我们可以把方法、变量放到对象里面。更高级的组织形式可以做更复杂的程序。

你可能感兴趣的:(java基础,java)