在上海乐字节学习Java的第十五天

Java多态(上)

多态意味着允许不同类的对象对同一消息做出不同的响应

编译时多态(设计时多态,一般为方法重载)

运行时多态(程序运行时动态决定调用哪个方法)

必要条件:
满足继承关系
父类引用指向子类对象
从一定角度来看,封装和继承几乎都是为多态准备的
现实中,多态的例子数不胜数
动物们都有吃东西、跑、跳、叫的方法,不同的动物表现方式不同

类型转换向上转型(Upcast):将子类型转换为父类型
隐式/自动类型转换,是小类型到大类型的转换
对于向上的类型转换,不需要显示指定,即不需要加上前面的小括号和父类类型名
向下转型(Downcast):将父类型转换为子类型
将一个指向子类对象的父类引用赋值给一个子类的引用
强制类型转换,是大类型到小类型
父类型的引用必须指向转型的子类的对象,即指向谁才能转换谁。不然也会编译出错
通过instanceof运算符,来解决引用对象的类型,避免类型转换的安全性问题,提高代码的强壮性

注意
父类引用指向子类实例时,可以调用子类重写父类的方法以及直接继承父类的方法,无法调用子类的特有的方法
静态static方法属于特殊情况,静态方法只能继承,不能重写。调用的时候用谁的引用,则调用谁的版本
代码实现

Animal类

package com.SH.animal;

//抽象类:不允许实例化,可以通过向上转型,指向子类实例
public abstract class Animal {
	//属性:昵称、年龄
	private String name;
	private int month;
	
	public Animal(){
		
	}
	
	public Animal(String name,int month){
		this.name=name;
		this.month=month;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getMonth() {
		return month;
	}

	public void setMonth(int month) {
		this.month = month;
	}
	
	//方法:吃东西
	//抽象方法:不允许包含方法体;子类中需要重写父类的抽象方法,否则,子类也是抽象类
	//static final private不能与abstract并存
	public abstract void eat();
	
	public static void say(){
		System.out.println("动物间打招呼");
	}
}

Cat类


package com.SH.animal;

public class Cat extends Animal {
	//属性:体重
	private double weight;
	
	public Cat(){
		
	}
	
	public Cat(String name,int month,double weight){
		super(name,month);
//		this.setMonth(month);
		this.weight=weight;
	}

	public double getWeight() {
		return weight;
	}

	public void setWeight(double weight) {
		this.weight = weight;
	}
	
	
	//方法:跑动
	public void run(){
		System.out.println("小猫快乐的奔跑");
	}
	
	
	//方法:吃东西(重写父类方法)
	@Override
	public void eat() {
		System.out.println("猫吃鱼~~");
	}
	
	public static void say(){
		System.out.println("小猫碰胡须");
	}

	public void playBall() {
		// TODO Auto-generated method stub
		System.out.println("小猫喜欢玩线球");
	}

Dog类

package com.SH.animal;

public class Dog extends Animal{
	//属性:性别
	private String sex;
	
	public Dog(){
		
	}
	
	public Dog(String name,int month,String sex){
		this.setMonth(month);
		this.setName(name);
		this.setSex(sex);
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}
	
	
	//方法:睡觉
	public void sleep(){
		System.out.println("小狗有午睡的习惯");
	}
	
	
	//方法:吃东西(重写父类方法)
	@Override
	public void eat() {
		System.out.println("狗吃肉~~");
		
	}
}

Test类


package com.SH.test;

import com.SH.animal.Animal;
import com.SH.animal.Cat;
import com.SH.animal.Dog;

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
//		Animal one=new Animal();//1

向上转型、隐式转型、自动转型
父类引用指向子类实例,可以调用子类重写父类的方法以及父类派生的方法,无法调用子类独有方法

注意:父类中的静态方法无法被子类重写,所以向上转型之后,只能调用到父类原有的静态方法
小类转型为大类

		*/
		Animal two=new Cat();//2
		two.say();
		Cat cat=(Cat)two;
		cat.say();

		Cat cat=new Cat();
		two=cat;
		Animal three=new Dog();//3
		
		one.eat();
		two.eat();
		two.setMonth(2);
		two.getMonth();
		two.run();
		three.eat();
		System.out.println("=================");
		/*向下转型、强制类型转换
		 * 子类引用指向父类对象,此处必须进行强转,可以调用子类特有的方法
		 * 必须满足转型条件才能进行强转
		 * instanceof运算符:返回true/false
		 */
	if(two instanceof Cat){
			Cat temp=(Cat)two;
			temp.eat();
			temp.run();
			temp.getMonth();
			System.out.println("two可以转换为Cat类型");
		}
	
		if(two instanceof Dog){
			Dog temp2=(Dog)two;
			temp2.eat();
		temp2.sleep();
			temp2.getSex();
			System.out.println("two可以转换为Dog类型");
	}

		if(two instanceof Animal){
			System.out.println("Animal");
		}
	
		if(two instanceof Object){
			System.out.println("Object");
	}
		

类型转换案例
Master类


package com.SH.animal;

public class Master {
喂宠物
喂猫咪:吃完东西后,主人会带着去玩线球
喂狗狗:吃完东西后,主人会带着狗狗去睡觉
养兔子、养鹦鹉、养乌龟

方案1:编写方法,传入不同类型的动物,调用各自的方法

public void feed(Cat cat){
cat.eat();
cat.playBall();
public void feed(Dog dog){
dog.eat();
dog.sleep();

方案2:编写方法传入动物的父类,方法中通过类型转换,调用指定子类的方法

public void feed(Animal obj){
obj.eat();
if(obj instanceof Cat){
Cat temp=(Cat)obj;
temp.playBall();
}else if(obj instanceof Dog){
Dog temp=(Dog)obj;
temp.sleep();
}

	

饲养何种宠物
空闲时间多:养狗狗

空闲时间不多:养猫咪

方案1:

public Dog hasManyTime(){
System.out.println("主人休闲时间比较充足,适合养狗狗");
return new Dog();
public Cat hasLittleTime(){
System.out.println("主人平时比较忙碌,适合养猫咪");
return new Cat();

方案2:

public Animal raise(boolean isManyTime){
if(isManyTime){
System.out.println("主人休闲时间比较充足,适合养狗狗");
return new Dog();
}else{
System.out.println("主人平时比较忙碌,适合养猫咪");
return new Cat();
}

MasterTest类

package com.SH.test;
import com.SH.animal.Animal;
import com.SH.animal.Cat;
import com.SH.animal.Dog;
import com.SH.animal.Master;
public class MasterTest {
public static void main(String[] args) {
Master master=new Master();
Cat one=new Cat();
Dog two=new Dog();
master.feed(one);
master.feed(two);
System.out.println("=============");
boolean isManyTime=false;
Animal temp=master.raise(isManyTime);
if(isManyTime){
temp=master.hasManyTime();
}else{
temp=master.hasLittleTime();
System.out.println(temp);
}

抽象类&抽象方法
应用场景:
某个父类只是知道其他子类应该包含怎样的方法,但无法准确知道这些子类如何实现这些方法

abstract定义抽象类
抽象类不能直接实例化,只能被继承,可以通过向上转型完成对象实例
abstract定义抽象方法,不需要具体实现
包含抽象方法的类是抽象类
抽象类中可以没有抽象方法
子类如果没有重写父类所以抽象方法,则也要定义为抽象类
abstract不能与 static、final、private共存
抽象方法在子类实现时访问权限必须大于等于父类方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值