java(07)多态、抽象类、接口

多态

如何构成多态?

多态存在的必要条件:

1.有继承关系

2.有方法重写

3.父类引用指向子类对象

多态特点:

1.成员变量: 编译时期观察左边类型,运行时期看左边类型

2.静态方法:编译时期观察左边类型,运行时期看左边类型

3.构造方法:帮助子类初始化父类继承的成员

4.成员方法: 编译时期观察左边类型,运行时期看右边类型(运行时指向的是子类的成员方法)

5.简化了代码,提高了维护下和扩展性

public class PolymorphismDemo01 {
	public static void main(String[] args) {
		// 3.父类引用指向子类对象  (注:该种引用看不到子类自己独立拥有的成员方法,若要使用需要强制转换)
		CutterMan c = new Hairdresser();
		// 使用多态
		c.cut();//此时无法输出子类特有的成员方法“唱歌”
		
		c = new Doctor();
		
		c.cut();
		
		c = new Director();
		
		c.cut();//此时无法输出子类特有的成员方法“拍电影”
		
		//4.强转转换:格式:<子类型> <引用变量名> = (<子类型> )<父类型的引用变量>;
		Hairdresser h =(Hairdresser) c;
		h.sing();//输出:唱歌
		Director d = (Director) c;
		d.makeMovie();//输出:拍电影
	}
}


class CutterMan {
	public void cut() {
		System.out.println("爱怎么cut怎么cut");
	}
}

class Hairdresser extends CutterMan {
	public void cut() {
		System.out.println("剪头发");
	}
	public void sing() {
		System.out.println("唱歌");
	}
}

class Doctor extends CutterMan {
	@Override
	public void cut() {
		System.out.println("动手术");
	}
}

class Director extends CutterMan {
	@Override
	public void cut() {
		System.out.println("暂停");
	}
	public void makeMovie(){
		System.out.println("拍电影");
	}
}

多态的缺点:通过父类引用无法访问子类所特有的方法。

若想要访问子类特有的方法,则需要通过向下转型来强制转换。

​ 转型格式:<子类型> <引用变量名> = (<子类型> )<父类型的引用变量>;

在向下转型的过程中可能会遇到如下异常情况:

java.lang.ClassCastException

异常名称: 类型转换异常

产生原因: 在向下转型的过程中没有转换成真实的类型

解决类型转换异常的办法: 在向下转型的过程中对父类的所有子类做类型检查

使用 instanceof 关键字检查类型;

格式: 左边对象 instanceof 右边类: 判断左边对象是否属于右边类的实例,返回boolean类型

例题::
实现主人与宠物玩耍功能 play
和狗狗玩接飞盘游戏。
和企鹅玩游泳游戏。
编写测试类测试
分析:
给Dog添加接飞盘方法catchingFlyDisc( )
给Penguin添加游泳方法swimming( )
给主人添加play(Pet pet)方法
思考:如果还需要再主人类中添加赠送宠物的方法呢?

public class Dedo01 {
	public static void main(String[] args) {
		//		Hoster h = new Hoster();
		Hoster h = new Hoster("小明", 3, 3);
		h.show();
		h.sendOut("dog", 3);
		h.playWithPet(new Dog());
	}
}

class Hoster {
	private String name;
	private int dogCount;
	private int penguinCount;

	public Hoster() {

	}

	public Hoster(String name, int dogCount, int penguinCount) {
		super();
		this.name = name;
		this.dogCount = dogCount;
		this.penguinCount = penguinCount;
	}

	public void show() {
		System.out.println(name + "有狗 " + dogCount + "只,有企鹅" + penguinCount + "只");
	}

	public void sendOut(String petName, int num) {
		System.out.print("送出" + petName + num + "只,");
		if (petName.equals("dog")) {
			this.dogCount = dogCount - num;
			System.out.println("剩下" + petName + dogCount + "只");
		} else if (petName.equals("penguin")) {
			this.penguinCount = penguinCount - num;
			System.out.println("剩下" + petName + penguinCount + "只");
		}
	}
						//Pet p =new Dog();
	public void playWithPet(Pet p) {
        // 实际上访问的是子类重写的方法,多态访问成员方法的特点
		p.play();
		if (p instanceof Dog && dogCount != 0) {
            //强制转换,访问的是子类成员特有的方法
			Dog dog = (Dog) p;
			dog.catchingFlyDisc();
		} else if (p instanceof Penguin && penguinCount != 0) {
			Penguin penguin = (Penguin) p;
			penguin.swimming();
		} else {
			System.out.println("该宠物已送光,没得玩了,呜呜~~");
		}
	}

	public String getPetName() {
		return name;
	}

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

	public int getDogCount() {
		return dogCount;
	}

	public void setDogCount(int dogCount) {
		this.dogCount = dogCount;
	}

	public int getPenguinCount() {
		return penguinCount;
	}

	public void setPenguinCount(int penguinCount) {
		this.penguinCount = penguinCount;
	}

}

class Pet {
	public void play() {
		System.out.println("和某某玩");
	}
}

class Dog extends Pet {
	public void play() {
		System.out.println("和狗玩");
	}

	public void catchingFlyDisc() {
		System.out.println("狗接飞盘");
	}
}

class Penguin extends Pet {
	public void play() {
		System.out.println("和企鹅玩");
	}

	public void swimming() {
		System.out.println("企鹅游泳");
	}
}

抽象类

抽象方法的概念: 一个仅仅给出方法声明,没有方法体的方法叫做抽象方法

抽象类的概念: 有一个抽象方法类必须是抽象类

抽象类的特点: 【精通】

1.抽象方法和抽象类使用 abstract 修饰

2.有一个抽象方法的类升级为抽象类

3.抽象类中一定有抽象方法吗? --> 不一定

4.没有抽象方法的类有意义吗? --> 有意义,防止外界创建对象

​ 防止外界创建对象的方式:

​ a.构造方法私有
​ b.抽象类

​ c.接口

​ d.内部类

5.Cannot instantiate the type Animal(抽象类不能够实例化)

6.如果你想要 “实例化”,可以使用多态 【抽象类 强制使用者 利用多态】

7.抽象类的子类特点:

​ a.如果子类不想要实现父类的所有抽象方法,那么子类也是升级为抽象类

​ b.如果子类想要实现父类的抽象方法,那么就必须实现父类所有的抽象方法

8.抽象类和普通类的区别:

​ 抽象类和普通类一模一样,只不过多了一个抽象方法

9.抽象类中的 成员变量,成员方法,构造方法,常量,静态方法的存在有什么意义呢?

​ 成员变量: 给子类使用

​ 成员方法: 给子类使用

​ 构造方法: 帮助子类初始化父类继承下来的成员

抽象方法: 用于给子类重写,方便构成多态

​ 常量: 直接通过类名即可方法,不仅给子类,给所有的类用

​ 静态方法: 直接通过类名即可方法,不仅给子类,给所有的类用

总结: 抽象类就是一个彻头彻尾的 服务类,服务于子类,燃烧自己,照亮孩子

补充:抽象方法它能够和 native private final static 共存吗?

native: 本地方法,C实现的,有方法体,abstract没有方法体,不能共存

private: 私有修饰的方法不能够给子类继承,更不可能重写了,abstract就是用来给子类重写的 (冲突)

final: final修饰方法不能够给子类重写,abstract就是用来给子类重写的 (冲突)

static: static修饰方法方便别人调用,别人调用的方法肯定是希望实现好的,abstract没有方法体,没有实现的,所以没有意义

抽象方法到底应该使用那些关键字修饰? --> public、 protected

public class AbstractDemo02 {
	public static void main(String[] args) {
		// Animal an = new Animal();
		Dog dog = new Dog(); // 面向具体编程
		Animal an = new Dog(); // 面向抽象编程
		// 面向接口编程
	}
}

//抽象类
abstract class Animal {

	String name;
	int age;

	public static final int NUM = 100;

	public Animal() {
	}

	public Animal(String name, int age) {
		this.name = name;
		this.age = age;
	}

	//抽象方法
	public /*static*/ /*final*/ /*private*/ /*native*/ abstract void bark();

	public abstract void show();

	public void method() {
		System.out.println("Animal.method()");
	}
}

class Dog extends Animal {

	public Dog() {
	}

	public Dog(String name, int age) {
		super(name, age);
	}

	@Override
	public void bark() {
		System.out.println("狗叫");
	}

	@Override
	public void show() {
		System.out.println("Dog show");
	}

}

2、例题:

编写交通工具类,具有前进run()功能,子类有自行车、小轿车、地铁,重写父类方法,主人有属性name,age属性,方法回家goHome(交通工具),需要使用交通工具,使用抽象类优化程序。

public class Demo02 {
	public static void main(String[] args) {
		Host h = new Host("小明", 30);
		Conveyance c = new Car();
		h.goHome(c);
		h.goHome(new Subway());
		h.goHome(new Bike());
	}
}

class Host {
	private String name;
	private int age;

	public Host() {

	}

	public Host(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public void goHome(Conveyance c) {
		c.run();
	}

	public String getName() {
		return name;
	}

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

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

}

abstract class Conveyance {
	public abstract void run();
}

class Bike extends Conveyance {
	@Override
	public void run() {
		System.out.println("骑自行车回家");
	}
}

class Car extends Conveyance {
	public void run() {
		System.out.println("开轿车回家");
	}
}

class Subway extends Conveyance {

	@Override
	public void run() {
		System.out.println("坐地铁回家");
	}
}

接口

接口里面全都是抽象方法,接口里面就是一个声明而已,没有实现。格式:

interface 接口名 {

​ 常量;

​ 抽象方法;

​ // 在JDK1.8之后还可以有默认方法和静态方法

接口的实现类格式:

class 接口的实现类 implements 接口 {

}

理解: 接口和抽象类的区别 接口和继承的关系

接口的特点: 【精通】

1.接口使用 interface 修饰,是一种特殊的类,是一种比抽象类还要抽象的类

2.接口是常量和抽象方法的集合,在JDK1.8之后还可以有默认方法和静态方法

3.常量默认省略了public static final

​ 方法默认省略了 public abstract

4.接口不能够实例化

5.如果我想要"实例化",利用多态 【父类引用(接口) 指向子类(接口的实现类) 对象】

6.接口的实现类特点:

​ a.如果一个类想要实现一个接口,就必须实现该接口当中所有的抽象方法

​ b.如果一个类不想实现接口当中的方法,那么该类必须升级为接口

7.接口是一种完全抽象,但是在JDK1.8之后可以使用默认方法和静态方法

8.接口是一种标准,是一种规范

9.接口是用来扩展功能

10.接口是灵活的

11.接口是规范,实现接口的功能还是属于第三方来实现的

12.接口 和 类之间的关系

​ 类和类 单继承 不可以实现

​ 类和接口 不可以继承 多实现

​ 接口和接口 多继承 不可以实现

13.接口只是一个规范,而抽象类是模板,部分规范, 普通类是完全模板

接口习题:

  • 1、要求如下:
    (1) 所有的可以拨号的设备都应该有拨号功能 (Dailup)
    (2) 所有的播放设备都可以有播放功能(Play)。
    (3) 所有的照相设备都有拍照功能(takePhoto)。
    (4) 定义一个电话类 Telephone,有拨号功能。
    (5) 定义一个Dvd类有播放功能。
    (6) 定义一个照相机类 Camera, 有照相功能。
    (7) 定义一个手机类 Mobile, 有拨号,拍照,播放功能。
    (8) 定义一个人类 Person, 有如下方法:
    <1> 使用拨号设备 use (拨号设备)
    <2> 使用拍照设备 use(拍照设备)
    <3> 使用播放设备 use(播放设备)
    <4> 使用拨号 播放 拍照设备 use(拨号播放拍照设备)
    (9) 编写测试类Test 分别创建人,电话,Dvd,照相机,手机对象,让人使用这些对象

  • public class Demo03 {
    	public static void main(String[] args) {
            // 利用多态来创建主人对象
    		AbsPerson p = new Master("小宁");
            // 利用多态来创建电话
            IDailup dailup = new Telephone();
    		p.use(dailup);
    		p.use(new Dvd());
    		p.use(new Camera());
    		p.use(new Mobile());
    	}
    }
    
    abstract class AbsPerson {
    	protected String name;
    
    	public AbsPerson() {
    
    	}
    
    	public AbsPerson(String name) {
    		this.name = name;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public abstract void use(IDailup dailup);
    
    	public abstract void use(IPlay play);
    
    	public abstract void use(ITakePhoto takePhoto);
    
    	public abstract void use(IDailupPlayTakephoto dailupPlayTakephoto);
    
    }
    
    class Master extends AbsPerson {
    	public Master() {
    
    	}
    
    	public Master(String name) {
    		super(name);
    	}
    
    	@Override
    	public void use(IDailup dailup) {
    		dailup.dailup();
    	}
    
    	@Override
    	public void use(IPlay play) {
    		play.play();
    	}
    
    	@Override
    	public void use(ITakePhoto takePhoto) {
    		takePhoto.takePhoto();
    	}
    
    	@Override
    	public void use(IDailupPlayTakephoto dailupPlayTakephoto) {
    		dailupPlayTakephoto.dailup();
    		dailupPlayTakephoto.takePhoto();
    		dailupPlayTakephoto.play();
    	}
    
    }
    
    interface IDailup {
    	void dailup();
    }
    
    interface IPlay {
    	void play();
    }
    
    interface ITakePhoto {
    	void takePhoto();
    }
    
    interface IDailupPlayTakephoto {
    	void dailup();
    
    	void play();
    
    	void takePhoto();
    }
    
    class Telephone implements IDailup {
    	public void dailup() {
    		System.out.println("电话拨号");
    	}
    }
    
    class Dvd implements IPlay {
    
    	@Override
    	public void play() {
    		System.out.println("DVD播放");
    	}
    }
    
    class Camera implements ITakePhoto {
    
    	@Override
    	public void takePhoto() {
    		System.out.println("照相机照相");
    	}
    }
    
    class Mobile implements IDailupPlayTakephoto {
    
    	@Override
    	public void dailup() {
    		System.out.println("手机拨号");
    	}
    
    	@Override
    	public void play() {
    		System.out.println("手机播放");
    	}
    
    	@Override
    	public void takePhoto() {
    		System.out.println("手机拍照");
    	}
    
    }
    
    
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值