0
点赞
收藏
分享

微信扫一扫

Java向上转型

闲云困兽 2022-03-11 阅读 21

一、普通类示例

父类

package 普通类向上转型;
 
public class Father {
	public int age = 48;
	public void sayAge() {
		System.out.println("我的年龄是:"+age);
	}
	public void myDaughter() {
		System.out.println("我女儿18岁");
	}
}

子类:

package 普通类向上转型;
 
public class Daughter extends Father{
	public int age = 18;
	public String sex = "女";
	@Override
	public void sayAge() {
		System.out.println("我的年龄是:"+age);
	}
	
	public void saySex() {
		System.out.println("我的性别是:"+sex);
	}
}

测试类:

package 普通类向上转型;
 
public class Test {
 
	public static void main(String[] args) {
		System.out.println("------输出各自属性和方法------");
		Father father = new Father();
		System.out.println(father.age);
		father.sayAge();
		
		System.out.println("----------");
		
		Daughter daughter = new Daughter();
		System.out.println(daughter.age);
		daughter.sayAge();
		System.out.println(daughter.sex);
		daughter.saySex();
		
		System.out.println("------输出向上转型后的,属性和方法------");
		Father a = new Daughter();
		System.out.println(a.age);
		// a 没有了sex属性
		a.sayAge();
		// a 没有了saySex方法
		a.myDaughter();
	}
 
}

输出结果:

------输出各自属性和方法------
48
我的年龄是:48
----------
18
我的年龄是:18
女
我的性别是:女
------输出向上转型后的,属性和方法------
48
我的年龄是:18
我女儿18

总结:可以看出,子类向上转型后。

  1. 属性和方法,父类有的才能保留,子类特有的属性和方法,都消失。——测试类中,a不能访问sex属性和saySex方法

  2. 如果子类重写了父类的方法,就调用子类重写的方法。否则掉调用父类方法——测试类中,输出a.age,结果为48,说明a的属性指向父类属性,sayAge输出18,说明调用了子类方法。(因为子类中调用age变量,指向的是子类的age=18)

图示
在这里插入图片描述

二、抽象类的向上转型

与上边写法,结论都一样,不再详讲,放个代码,供大家看看:

父类(抽象类)

package 抽象类向上转型;
 
public abstract class Father {
	
	public int age = 48;
	
	public abstract void sayAge();
	
	public void myDaughter() {
		System.out.println("我女儿18岁");
	}
}

子类

package 抽象类向上转型;
 
public class Daughter extends Father{
	
	public int age = 18;
	public String sex = "女";
	@Override
	
	public void sayAge() {
		System.out.println("我的年龄是:"+age);
	}
	
	public void saySex() {
		System.out.println("我的性别是:"+sex);
	}
 
}

测试类:

package 抽象类向上转型;
 
public class Test {
 
	public static void main(String[] args) {
		System.out.println("------输出各自属性和方法------");
		System.out.println("抽象类不能直接实例化");
		
		System.out.println("----------");
		
		Daughter daughter = new Daughter();
		System.out.println(daughter.age);
		daughter.sayAge();
		System.out.println(daughter.sex);
		daughter.saySex();
		
		System.out.println("------输出向上转型后的,属性和方法------");
		Father a = new Daughter();
		System.out.println(a.age);
		// a 没有了sex属性
		a.sayAge();
		// a 没有了saySex方法
		a.myDaughter();
	}
 
}
------输出各自属性和方法------
抽象类不能直接实例化
----------
18
我的年龄是:18
女
我的性别是:女
------输出向上转型后的,属性和方法------
48
我的年龄是:18
我女儿18

三、接口向上转型:

接口:

package 接口向上转型;
 
public interface Father {
	
	int AGE = 48;
	
	public abstract void sayAge();
	
}

实现类:

package 接口向上转型;
 
public class Daughter implements Father{
	
	public int age = 18;
	public String sex = "女";
	
	@Override
	public void sayAge() {
		System.out.println("我的年龄是:"+age);
	}
	
	public void saySex() {
		System.out.println("我的性别是:"+sex);
	}
 
}

测试类:

package 接口向上转型;
 
public class Test {
 
	public static void main(String[] args) {
		System.out.println("------输出各自属性和方法------");
		System.out.println("抽象类不能直接实例化");
		
		System.out.println("----------");
		
		Daughter daughter = new Daughter();
		System.out.println(daughter.age);
		daughter.sayAge();
		System.out.println(daughter.sex);
		daughter.saySex();
		
		System.out.println("------输出向上转型后的,属性和方法------");
		Father a = new Daughter();
		System.out.println(a.AGE);
		// a 没有了sex属性
		a.sayAge();
		// a 没有了saySex方法
	}
 
}

总结:

  1. 调用的方法一定是实现类的方法。——因为接口中不能出现普通方法(jdk1.8可以写,但不常用)。

  2. 常量指向的是接口中的常量。——输出a.AGE结果是48。

作用:使用向上转型可以,提高代码的简洁性、灵活性、适用性。

话说有对比才会有伤害,咱们用向上转型和不用向上转型,做同一个工作试试。

假设我们要进行一项调查,随机抽取10个人,查看他的职业(咱们只写学生和老师两个职业)。

不使用向上转型:

学生:

package 向上转型的应用.做参数;
 
public class Student {
 
	public void work() {
		System.out.println("我是学生,我的工作是学习");
	}
 
}

老师:

package 向上转型的应用.做参数;
 
public class Teacher {
 
	public void work() {
		System.out.println("我是老师,我的工作是教学");
	}
 
}

测试类:

package 向上转型的应用.做参数;
 
public class Test {
 
	public static void main(String[] args) {
 
		// 模拟10次随机抽人
		for (int i = 0; i < 10; i++) {
			// 生成随机数,模拟随机抽人
			final double d = Math.random();
			final int j = (int)(d*10);
			if (j<5) {
				// 传递抽取的人
				sayHerJob(new Student());
			} else {
				// 传递抽取的人
				sayHerJob(new Teacher());
			}
 
		}
 
	}
 
	private static void sayHerJob(Student s) {
		s.work();
	}
	private static void sayHerJob(Teacher t) {
		t.work();
	}
}

运行结果:

我是老师,我的工作是教学
我是老师,我的工作是教学
我是老师,我的工作是教学
我是学生,我的工作是学习
我是学生,我的工作是学习
我是老师,我的工作是教学
我是老师,我的工作是教学
我是老师,我的工作是教学
我是学生,我的工作是学习
我是学生,我的工作是学习

可以看到,有两个职业sayHerJob方法就复写了一遍,如果世界上有1881种职业,你就复写1880次方法???

显然不可能,代码冗余,死板。

再来看看咱们的向上转型

我们可以看到学生和老师都是人,我们只问她们职业。

这句话是什么意思?约束——接口!

Person接口

package 向上转型的应用.做参数;
 
public interface Person {
	void work();
}

学生:

package 向上转型的应用.做参数;
 
public class Student implements Person {
 
	@Override
	public void work() {
		System.out.println("我是学生,我的工作是学习");
	}
 
}

老师

package 向上转型的应用.做参数;
 
public class Teacher implements Person {
 
	@Override
	public void work() {
		System.out.println("我是老师,我的工作是教学");
	}
 
}

测试:

package 向上转型的应用.做参数;
 
public class Test {
 
	public static void main(String[] args) {
 
		Person p = null;
		// 模拟10次随机抽人
		for (int i = 0; i < 10; i++) {
			// 生成随机数,模拟随机抽人
			final double d = Math.random();
			final int j = (int)(d*10);
			if (j<5) {
				// 向上转型
				p = new Student();
			} else {
				// 向上转型
				p = new Teacher();
			}
 
			// 传递抽取的人
			sayHerJob(p);
		}
 
	}
 
	private static void sayHerJob(Person p) {
		p.work();
	}
}

运行结果:

我是老师,我的工作是教学
我是老师,我的工作是教学
我是老师,我的工作是教学
我是老师,我的工作是教学
我是老师,我的工作是教学
我是老师,我的工作是教学
我是老师,我的工作是教学
我是老师,我的工作是教学
我是学生,我的工作是学习
我是老师,我的工作是教学

把学生和老师,都向上转型成Peron,参数类型都一样,只用写一个方法就行,极大的提高了代码的简洁性、适应性。

另外,这里向上转型是作为参数传递过去的,相应的,我们也可以作为返回值去写,同样可以极大的提高撸代码的效率。

总结

  1. 调用的方法是实现类的方法;
  2. 调用的属性是父类的属性;
  3. 实现类特有的方法不能使用;

作用

  1. 体现了Java抽象的编程思想;
  2. 提高代码的简洁性(减少重复代码)、灵活性、适用性(提高系统扩展性);
举报

相关推荐

0 条评论