文章
时间轴
标签
音乐室
友人帐
一刻时光
清单
留言板
相册
算法海洋
关于
Slcpの童话镇 🏰
写文章
多态、接口
原创
Java
面向对象
后端
发布日期:
2019年08月15日
文章字数:
5.1k
阅读次数:
1116
阅读时长:
0小时0分0秒
## 多态 ### 多态的实现 * 多态的概念 * 同一个对象,在不同时刻表现出来的不同形态。 * 举例:狗 ~~~ 我们可以说狗是狗:狗类 dog = new 狗类(); 我们也可以说狗是动物:动物 dog = new 狗(); 这里的狗在不同的时刻表现出来了不同的形态,这就是多态 ~~~ * 多态的前提和体现 > `有继承/实现关系` > > `有方法重写` > > `有父类引用指向子类对象` * 代码演示 ~~~java package com.itheima.day03.domain; /** * @Author: ✎﹏ Sunflower丶 * @Specification: 动物类 */ public class Animal { public void eat(){ System.out.println("动物吃饭"); } } ~~~ ~~~java package com.itheima.day03.domain; /** * @Author: ✎﹏ Sunflower丶 * @Specification: 狗类 */ public class Dog extends Animal { @Override public void eat() { System.out.println("小余啃骨头"); } public void watchHome() { System.out.println("狗看家"); } } ~~~ ~~~java package com.itheima.day03.test; import com.itheima.day03.domain.Animal; import com.itheima.day03.domain.Dog; /** * @Author: ✎﹏ Sunflower丶 * @Specification: 测试类 */ public class Test { /* 多态的前提: 1. 要有(继承 \ 实现)关系 2. 要有方法重写 3. 要有父类引用, 指向子类对象 */ public static void main(String[] args) { //当前事物,是一只狗 Dog dog = new Dog(); //这是一只动物 Animal animal = new Dog(); animal.eat(); } } ~~~ ### 多态中成员访问特点 * 成员访问特点 * 构造方法 同继承一样,子类会通过super访问父类的构造方法 * 成员变量 `编译看左边,执行看左边` * 成员方法 `编译看左边,执行看右边` * 代码演示 ~~~java //父类 public class Fu { int num = 10; public void method(){ System.out.println("Fu.. method"); } } ~~~ ~~~java //子类 public class Zi extends Fu { int num = 20; public void method(){ System.out.println("Zi.. method"); } } ~~~ ~~~java public class Test2 { /* 多态的成员访问特点: 成员变量: 编译看左边 (父类), 运行看左边 (父类) 成员方法: 编译看左边 (父类), 运行看右边 (子类) */ public static void main(String[] args) { Fu f = new Zi(); System.out.println(f.num); f.method(); } } ~~~ > 为什么成员变量与成员方法的访问结果不一样? > > `因为成员方法有重写,而成员变量没有` ### 多态的好处和弊端 - 好处 `提高程序的扩展性` > 具体体现:定义方法时候,使用父类型作为参数,在使用的时候,使用具体的子类型参与操作 - 弊端 `不能使用子类的特有功能(成员)` ### 多态中的转型 | 转型 | 格式 | 解释 | | ---------- | --------------------------------- | -------------------- | | `向上转型` | 父类引用 对象名 = new 子类型(); | 父类引用指向子类对象 | | `向下转型` | 子类型 对象名 = (子类型)父类引用; | 父类引用转向子类对象 | * 代码演示 ~~~java package com.itheima.day03.domain; /** * @Author: ✎﹏ Sunflower丶 * @Specification: 猫类 */ public class Cat extends Animal { @Override public void eat() { System.out.println("猫吃鱼"); } public void catchMouse() { System.out.println("猫抓老鼠"); } } ~~~ ~~~java package com.itheima.day03.test; import com.itheima.day03.domain.Animal; import com.itheima.day03.domain.Dog; /** * @Author: ✎﹏ Sunflower丶 * @Specification: 测试类 */ public class Test { public static void main(String[] args) { //向上转型 : 父类引用指向子类对象 Animal a = new Cat(); a.eat(); //输出猫吃鱼 // 多态的弊端: 不能调用子类特有的成员 // a.catchMouse(); // 2. 向下转型 : 从父类类型, 转换回子类类型 Cat c = (Cat) a; a.catchMouse(); //多态的好处:提高程序的扩展性 //可以接收一切动物子类。 Dog d = new Dog(); useAnimal(d); useAnimal(a); useAnimal(c); } public static void useAnimal(Animal a){ a.eat(); } } ~~~ ### 多态中转型存在的风险和解决方案 + 风险 如果被转的引用类型变量,对应的`实际类型`和`目标类型`不是同一种类型,那么在转换的时候就会出现`ClassCastException ` + 关键字`instanceof` + 使用格式: `变量名 instanceof 类型` > 通俗的理解:`判断关键字左边的变量,是否是右边的类型,返回boolean类型结果` + 代码演示 ~~~java package com.itheima.day03.test; import com.itheima.day03.domain.Animal; import com.itheima.day03.domain.Dog; /** * @Author: ✎﹏ Sunflower丶 * @Specification: 测试类 */ public class Test { public static void main(String[] args) { useAnimal(new Dog()); useAnimal(new Cat()); } public static void useAnimal(Animal a){ //Animal a = new Dog(); a.eat(); //a.catchMouse() ClassCastException 类型转换异常 // 判断a变量记录的类型, 是否是Dog if(a instanceof Dog) { Dog dog = (Dog) a; dog.watchHome(); }else if(a instanceof Cat) { Cat c = (Cat) a; c.catchMouse(); } } } ~~~ ## 接口 ### 接口的概述 * 当一个类中所有的方法都是抽象方法,我们就将其定义为`接口` * 接口也是一种引用数据类型,它比抽象类还要抽象。 > 接口就是一种`公共的规范标准`,只要符合规范标准,大家都可以通用。 * Java中接口存在的两个意义 * `规则的定义`,用来定义规范 * `程序的扩展性`,用来做功能的拓展 接口的定义和特点 * 接口用关键字`interface`来定义 * 接口不能`实例化` * 接口与类之间的`实现关系`,通过`implements`关键字表示 * 接口的子类(实现类) * 要么`重写`接口中的`所有`抽象方法 * 要么是`抽象类`(不建议) * 接口的定义格式 > `public interface 接口名{}` * 类实现接口的格式 * 普通类的实现 > `public class 类名 implements 接口名 {}` * 抽象类的实现 > `public abstract class 类名 {} implements 接口名 {}` * 范例: ~~~java public interface InterA { public abstract void add(); void del(); } ~~~ ~~~java public interface InterB { void upd(); } ~~~ ~~~java public abstract class Demo implements InterA{ } ~~~ ~~~java public class InterImpl implements InterA,InterB { @Override public void add() { } @Override public void del() { } @Override public void upd() { } } ~~~ 注意:`接口是可以多实现的` ### 接口中的成员特点 成员变量 * 常量 * 系统默认修饰:`public static final` 构造方法 * 没有 成员方法 * 只能是抽象方法 * 系统默认修饰:`public abstract` ### 类和接口的关系 - `类与类`的关系 继承关系,只能`单继承`,但是可以`多层继承` - `类与接口`的关系 实现关系,可以`单实现`,也可以`多实现`,还可以在继承一个类的同时实现多个接口 - `接口与接口`的关系 继承关系,可以`单继承`,也可以`多继承` ## 接口组成更新 ### 接口组成及更新概述 **`接口的组成`** - 常量 `public static final` - 抽象方法 `public abstract` - 默认方法(Java 8) - 静态方法(Java 8) - 私有方法(Java 9) `更新` * JDK8版本后 1. 允许在接口中定义非抽象方法,但是需要使用关键字default修饰,这些方法解释默认方法。 > 注意:`定义方法上的修饰符中的默认修饰符是以不写来表示,与default无关。` 2. 接口中允许定义static静态方法 * JDK9版本后 * 接口中允许定义private私有方法 ### 接口中默认方法 * 定义格式: > **public `default` 返回值类型 方法名(参数列表){ }** * 范例: ~~~java public default void show() {} ~~~ * 作用 `解决接口升级的问题` * 注意事项: > * `默认方法不是抽象方法`,所有不强制被重写,但可以被重写,`重写的时候去掉default关键字 ` > > - `public`可以省略,`default`不能省略 > - 如果`实现了多个接口`,多个接口中存在`相同的方法声明`,子类就必须对`该方法进行重写` ### 接口中静态方法 * 定义格式: > **public `static` 返回值类型 方法名(参数列表){ }** * 范例: ~~~java public static void show() {} ~~~ * 注意事项: > * 静态方法只能通过`接口名调用`,不能通过`实现类名`或者`对象名调用` > * `public`可以省略,`static`不能省略 ### 接口中私有方法 * 私有方法产生原因 Java 9中新增了`带方法体的私有方法`,这其实在Java 8中就埋下了伏笔:Java 8允许在接口中定义`带方法体的默认方法`和`静态方法`。这样可能就会引发一个问题:`当两个默认方法或者静态方法中包含一段相同的代码实现时`,程序必然考虑将这段实现代码抽取成一个`共性方法`,而这个共性方法是不需要让别人使用的,因此用`私有给隐藏起来`,这就是Java 9增加私有方法的必然性 * 定义格式 * 格式1: > **`private` 返回值类型 方法名(参数列表){ }** * 范例1: ~~~java private void show() {} ~~~ * 格式2 >**`private static` 返回值类型 方法名(参数列表) { }** * 范例2 ~~~java private static void show() { } ~~~ * 注意事项 > - 默认方法可以调用私有的静态方法和非静态方法 > - 静态方法只能调用私有的静态方法 ### 接口的使用思路 * 如果发现一个类中所有的方法都是抽象方法,那么就可以将该类,改进为一个接口 * 涉及到了接口大面积更新方法,而不想去修改每一个实现类,就可以将更新的方法,定义为带有方法体的默认方法 * 希望默认方法调用的更加简洁,可以考虑设计为static静态方法。(需要去掉default关键字) * 默认方法中出现了重复代码,可以考虑抽取出一个私有方法。(需要去掉default关键字) > 如果父类和接口中出现了`相同的方法声明`,但代码逻辑不一样,运行方法的时候,会`优先使用父类的代码逻辑`
您阅读这篇文章共耗时:
0小时16分34秒
文章链接:
https://www.slcp.top/article/read/28
版权声明:
本博客所有文章除特別声明外,均采用
CC BY 4.0
许可协议。转载请注明来源
Slcp
!
转载文章以及部分引用均为自己整理记录学习而用,若有侵权,请联系删除。
Java
面向对象
评论
Valine
Gitalk
目录
搜索
首页
前进
后退
刷新
申请友链
在线联系