目录
1.多态
在多态理解过程中直接伴随着一个实例的完成,以助于理解多态的使用方法和使用场景。
1.1 多态概述
1.1.1 为什么使用多态
当不确定要使用哪个子类来创建对象时,可以先创建父类对象,并将其赋值为某个子类,同时还可以设置控制语句控制父类对象指向哪个子类,根本目的时使代码更加简洁高效。
1.1.2 多态定义
多态就是父类引用指向子类对象
1.2 多态的实现
1.2.1 多态的三要素
(1)编写具有继承关系的父类和子类
(2)子类重写父类方法
(3)使用父类的引用指向子类的对象
public abstract class Pet{
public abstract void eat();
}
public final class Dog extends Pet{
//继承了Pet
public void eat(){
//重写了父类中的方法
System.out.println("吃狗粮");
}
}
public class Test{
public static void main(String[] args){
Pet pet = new Dog();//创建一个父类对象,将子类对象赋给它实现多态
}
}
1.2.2 多态表现形式
(1)使用父类作为方法形参实现多态
接上文,当父类有新的子类,例如Penguin时,可以改变pet指向的子类对象,实现不同的子类方法
public final class Penguin extends Pet{
public void eat(){
System.out.print("吃鱼");
}
}
//创建一个新的类Master为宠物添加喂食宠物的功能
public class Master{
public void feed(Pet pet){
pet.eat();//调用父类Pet中定义的抽象方法可以直接调用子类对应的方法
}
}
public class Test{
public static void main(String[] args){
Master master = new Master();
Pet pet = new Dog();
master.feed(pet);//结果为"吃狗粮"
pet = new Penguin();
master.feed(pet);//结果为"吃鱼"
}
}
(2)使用父类作为返回值实现多态
我们会发现上面需要手写代码来选择pet指向的子类对象很麻烦,那么我们可以在Master中加入一个选择子类的方法。
public Pet getPet(int choose){
//父类Pet作为返回值的类型
//先创建一个Pet对象
Pet pet = null;
//使用选择语句对choose进行判断
switch(choose){
case 1:
pet = new Dog();//选择1,则指向Dog类
break;
case 2:
pet = new Penguin();//选择2,则指向Penguin类
}
//返回赋值后的Pet对象
return pet;
}
public class Test{
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
Master master = new Master();
System.out.print("请选择您的宠物类型:(1、狗狗2、企鹅)");
int choose = scanner.nextInt();
Pet pet = master.getPet(choose);
master.feed(pet);//如果输入1显示"吃狗粮",输入2则显示"吃鱼"
}
}
1.3 多态中的类型转换
多态中的类型转换类似于基础数据的类型转换,也有自动转换和强制类型转换,并且遵循大小的规则。
1.3.1 向上转型
向上转型就是从子类转向父类,从小转到大的转换是可以实现自动转换,例如最初的案例中Pet pet = new Dog();实际上就是自动向上转换例子。
1.3.2 向下转型
向下转型是从父类转向子类,从大转小需要进行强制转换,在基础类型中的强制转换例如从double类型转向int类型我们可以使用(int)来实现,类似的,如果我们想将Pet类型转换成Dog类型,只需要使用(Dog)就行了,例如:
Pet pet = new Dog();//此时pet的类型为Pet
Dog dog =(Dog)pet;//先将pet转换为Dog类型再赋值给dog对象
一般情况下,强制类型转换会和下文中instanceof一起使用。
1.4 instanceof运算符
instanceof运算符的表达式返回值为boolean类型,用于判断某个对象的类是否与某个类一致,例如a instanceof A 是判断a对象是否属于A类,其中a一般是起初创建的父类对象在实现了多态转换之后的值,A为父类的某个子类。
下面结合instanceof运算符和强制类型转换在Master类中编写方法实现与宠物玩耍的功能,两个子类具有不同的方法。
Dog类的玩耍是catchFlyDisc()方法:
public final class Dog extends Pet{
public void eat(){
System.out.println("吃狗粮");
}
public void catchFlyDisc(){
System.out.println("接飞盘");
}
}
Penguin类的玩耍时swim()方法:
public final class Penguin extends Pet{
public void eat(){
System.out.print("吃鱼");
}
public void swim(){
System.out.print("游泳");
}
}
Master类中添加play()方法实现与宠物玩耍的功能:
public void play(Pet pet){
//同样需要一个Pet类型的形参
//利用判断语句和instanceof运算符来判断传入实参的类型
if(pet instanceof Dog){
Dog dog = (Dog)pet;//强制转换
dog.catchFlyDisc();//调用子类的独有方法
}else if(pet instanceof Penguin){
Penguin penguin = (Penguin)pet;//与上面相同
penguin.swim();
}
}
Test中调用play()方法:
public class Test{
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
Master master = new Master();
System.out.print("请选择您的宠物类型:(1、狗狗2、企鹅)");
int choose = scanner.nextInt();
Pet pet = master.getPet(choose);
master.feed(pet);
master.play(pet);//如果输入1显示"接飞盘",输入2则显示"游泳"
}
}
1.5 多态总结
多态实际上是利用类型转换机制,在父类和子类之间转换,实现快速调用父类中公有方法和子类中特有方法的方式。子类可以向父类自动转换,可以调用在子类中重写的公有方法,而利用强制转换和instanceof运算符可以实现对父类指向子类的判断,并调用该子类独有的方法。
2.接口
2.1 接口概述
2.1.1 什么是接口
(1)接口关键字 interface
(2)接口实际上为一个特殊的抽象类,因此无法实例化
(3)接口中定义的属性都是静态常量
(4)其中所有方法都默认有public abstract修饰
(5)同一个类可以实现多个接口,引入时,用implements关键字,多个接口用”,”隔开
(6)类使用接口时,必须将接口中定义的方法全部重写
2.1.2 接口是一种约定
接口中包含了使用该接口的规范,可以为该接口进行注释来解释何时使用该接口,以及该接口使用时需要注意的事项,定义的方法也代表了一种特殊规范,表示当使用该接口时,实现类必须要具有的某种功能(方法必须被重写)。
2.2 使用接口的步骤
(1)创建接口
右击包选择New-->Java Class选择interface选项,命名接口名称,点击确定。
(2)在接口中写入方法
public interface USB{
void charge();//约定USB接口的充电功能
}
(3)创建实现类引入接口并重写约定的方法
public class SlowUSB implements USB{
//implements为引入接口的关键字
public void charge(){
//重写接口约定的charge方法
System.out.print("慢速充电中...")
}
}
(4)调用方法
public class Test{
public static void main(String[] args){
USB usb = new SlowUSB();//创建一个USB对象指向实现类
usb.charge();//调用charge方法
}
}
注意:我们可以在同一个接口下创建多个实现类以实现不同的具体功能,实际上这种方式与之前学到的继承关系中的多态实现很相似,唯一不同的是实现类可以实现多个接口的功能,而继承只能继承一个类。
2.3 接口实例
2.3.1 要求
2.3.2 接口
public interface TheakePictures {
void takePictures();
}
public interface Network {
void networkConn();
}
public interface PlayWiring {
void play(String content);
}
2.3.3 父类与实现类
public abstract class Phone implements PlayWiring{
String brand;
String type;
public Phone(String brand, String type) {
this.brand = brand;
this.type = type;
}
public abstract void sendInfo();
public abstract void call();
public void info(){
System.out.println("这是一款型号为"+type+"的"+brand+"手机");
}
}
public class Commonphone extends Phone{
public Commonphone(String brand, String type) {
super(brand, type);
info();
}
public void sendInfo() {
System.out.println("发送文字信息......");
}
public void call() {
System.out.println("开始语音通话......");
}
public void play(String content) {
System.out.println("开始播放音乐《"+content+"》......");
}
}
public class Smartphone extends Phone implements Network,TheakePictures{
public Smartphone(String brand, String type) {
super(brand, type);
info();
}
public void sendInfo() {
System.out.println("发送带图片与文字的信息......");
}
public void call() {
System.out.println("开始视频通话......");
}
public void networkConn() {
System.out.println("已经启动移动网络......");
}
public void play(String content) {
System.out.println("开始播放视频《"+content+"》......");
}
public void takePictures() {
System.out.println("咔嚓......拍照成功");
}
}
2.3.4 测试类
public class Test {
public static void main(String[] args) {
String type;
String brand;
brand = "索尼爱立信";
type = "G502c";
Commonphone commonphone = new Commonphone(brand,type);
commonphone.play("热雪");
commonphone.sendInfo();
commonphone.call();
System.out.println();
brand = "HTC";
type = "I9100";
Smartphone smartphone = new Smartphone(brand,type);
smartphone.networkConn();
smartphone.play("小时代");
smartphone.takePictures();
smartphone.sendInfo();
smartphone.call();
}
}
2.3.5 结果
2.4 接口总结
接口实际上是一个特殊的抽象类,在其中可以定义约定的功能并让引入该接口的实现类必须重写这些功能。同一个类可以实现多个接口,相当于对多种功能模块进行组装,而这些功能模块的所有具备的功能就是用接口来约定的。使用接口可以大大提高编写代码的效率,减少错误,使代码的结构更明确,更便于维护。