文章目录
利用面向对象思想完成"考试系统"案例
分析:
-
概念模型(事物)
- Java学生
- 属性:姓名、年龄、班级、学号、…
- 行为:登录()、考试()
- UI学生
- 属性:姓名、年龄、班级、学号、…
- 行为:登录()、考试()
- Java学生
-
把概念模型中的共性内容,向上抽取,封装为:父类
- 父类:Student
- 属性:姓名、年龄、班级、学号
- 行为:登录()、考试()
- 父类:Student
一、多态
01_多态:多态的概述(了解)
目标
- 了解多态的基本概念
路径
- 多态的含义
- 使用多态的前提
- 多态的书写格式
多态的含义
面向对象的三个特性:
- 封装
- 继承(是建立封装的基础之上)
- 多态(是建立在继承的基础之上)
什么是多态?
-
事物的多种展现形态
-
举例: 数值:10
- 2进制表示形式:1010
- 10进制表示形式:10
- 8进制表示形式:12
- 16进制表示形式:A
多态的前提
在使用多态的前提条件:
-
有继承关系(学习接口后有实现关系)
-
子类重写父类中的方法
多态的书写格式
书写格式:父引用指向子类对象
父类 父引用 = new 子类();
创建子类对象:
方式1: JavaStudent javaStu = new JavaStudent(); //使用事物的本身类型来定义
方式2: Student stu = new JavaStudent(); //使用事物的父类型来定义
//父类
abstract class Student{
//属性
private String name;
//行为
public abstract void exam();//抽象方法
//getter、setter
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
}
//子类
class JavaStudent extends Student{
//重写抽象方法
public void exam(){
System.out.println("java学员,进行阶段考试")
}
}
//测试类
public static void main(String[] args){
//可以使用事物本身类型来定义
JavaStudent javaStu = new JavaStudent();
//可以使用事物的父类型来定义
Student stu = new JavaStudent();//父引用指向子类对象
//Student : 父类型
//stu : 父引用(父类对象)
//new JavaStudent() : 子类对象
}
小结
-
多态的概念:事物的多种展现形式
-
多态的代码格式:
-
父类 父对象 = new 子类(); //父对象引用了子类对象
-
02_多态:多态体现(了解)
目标
- 了解多态的体现方式
路径
- 多态的体现方式
多态的体现方式
在Java语言中,多态的体现划分为两类:
- 静态多态
- 也称为编译期多态
- 概念:同一个对象的不同行为体现
- 举例:同一个对象进行登录,可以有不同的登录方式(用户名/密码、手机验证码、人脸识别)
- 代码体现为:方法重载
- 动态多态
-
也称为运行期多态
-
概念:不同对象的相同行为体现
- 举例:不同的对象进行考试,对象都有考试功能(Java学生=>考试、UI学生=>考试)
-
代码体现为:方法重写
- 有继承关系(学习接口后有实现关系)
- 子类重写父类中的方法
-
小结
在java中多态的体现可以划分为:
- 静态多态:同一个对象的不同行为
- 代码实现:方法重载
- 动态多态:不同对象的相同行为
- 代码实现:方法重写
03_多态:静态多态
目标
- 清楚静态多态的使用方式
路径
-
案例分析
-
代码实现
案例分析
为"考试系统",开发登录功能,登录方式有3 种:
- 用户名/密码
- 手机验证码
- 人脸识别
思考:
- 学生登录
- 登录有3种形式:开发3个方法
代码实现
静态多态:
- 同一个对象的不同行为体现 (重载)
//父类
public abstract class Student {
private String number;//学号
private String name;//姓名
private int age;//年龄
private String classes;//班级
public Student() {
}
public Student(String number, String name, int age, String classes) {
this.number = number;
this.name = name;
this.age = age;
this.classes = classes;
}
//登录
public abstract boolean login(String name,String passwd);
public abstract boolean login(int phoneCode);
public abstract boolean login(String face);
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
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;
}
public String getClasses() {
return classes;
}
public void setClasses(String classes) {
this.classes = classes;
}
}
//子类:Java学生
public class JavaStudent extends Student{
public JavaStudent() {
}
public JavaStudent(String number, String name, int age, String classes) {
super(number, name, age, classes);
}
/**
* 登录:用户名和密码
* */
@Override
public boolean login(String name,String passwd){
Scanner sc = new Scanner(System.in);
System.out.print("用户名:");
String loginName = sc.next();
System.out.print("密码:");
String loginPwd =sc.next();
return true;
}
/**
* 登录:手机验证码
* */
@Override
public boolean login(int phoneCode){
Scanner sc = new Scanner(System.in);
System.out.print("请输入手机验证码:");
int pc = sc.nextInt();
return true;
}
/**
* 登录:人脸识别
* */
@Override
public boolean login(String face){
System.out.print("请不要动,人脸识别中...");
return true;
}
}
//考试系统
public class ExamSys {
public static void main(String[] args) {
init();
}
public static void init() {
System.out.println("******************考试系统******************");
System.out.println("请选择学科: 1) Java \t 2) UI");
int subjectNumber = new Scanner(System.in).nextInt();
switch (subjectNumber) {
case 1:
JavaStudent javaStu = new JavaStudent();
//考试前:先登录
if (login(javaStu)) {
System.out.println("登录成功!");
// TODO: 未完成的功能
}
break;
case 2:
UiStudent uiStu = new UiStudent();
if (login(uiStu)) {
System.out.println("登录成功!");
// TODO: 未完成的功能
}
break;
default:
System.out.println("选择错误,退出系统!");
System.exit(0);
}
}
//登录
public static boolean login(Student stu) {
System.out.println("---------------------------------------------");
System.out.println("请选择登录方式:");
System.out.println("1、用户名/密码");
System.out.println("2、手机验证码");
System.out.println("3、人脸识别");
int loginNumber = new Scanner(System.in).nextInt();
System.out.println("---------------------------------------------");
boolean result = false;
switch (loginNumber) {
case 1:
result = stu.login("用户名", "密码");
break;
case 2:
result = stu.login(40088);
break;
case 3:
result = stu.login("人脸数据");
break;
}
return result;
}
}
小结
静态多态:同一个对象,不同行为的展现
实现方式:方法重载(在一个类中)
04_多态:动态多态(重点)
目标
- 掌握动态多态的使用方式
路径
-
案例分析
-
代码实现
案例分析
为"考试系统",开发考试功能:
-
Java学生 => 考试
-
UI学生 => 考试
方法中除了对象不同外,其它代码都是类同(复用性很差)
解决方案:多态(动态多态)
代码实现:方法重写
-
Student stu1 = new JavaStudent();//多态的格式 Student stu2 = new UiStudent(); stu1.exam();//因为Student类中有exam()方法,所以可以调用 //在执行时,因为JavaStudent类重写了exam()方法,所以执行时使用重写后的方法 stu2.exam();//运行时调用UiStudent类中重写的exam()方法
思考:JavaStudent和UiStudent中有没有exam()方法?
答案:使用动态多态解决程序中复用性的问题
public void startExam(Student stu){
stu.exam();
}
代码实现
动态多态:
- 不同对象的相同行为体现 (重写)
//父类:学生
public abstract class Student {
private String number;//学号
private String name;//姓名
private int age;//年龄
private String classes;//班级
public Student() { }
public Student(String number, String name, int age, String classes) {
this.number = number;
this.name = name;
this.age = age;
this.classes = classes;
}
//考试
public abstract void exam();
//登录
public abstract boolean login(String name,String passwd);
public abstract boolean login(int phoneCode);
public abstract boolean login(String face);
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
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;
}
public String getClasses() {
return classes;
}
public void setClasses(String classes) {
this.classes = classes;
}
}
//子类:Java学生
public class JavaStudent extends Student{
public JavaStudent() { }
public JavaStudent(String number, String name, int age, String classes) {
super(number, name, age, classes);
}
/**
* 考试
*/
@Override
public void exam() {
System.out.println("Java学生,进行阶段性考试!");
}
/**
* 登录:用户名和密码
* */
@Override
public boolean login(String name,String passwd){
Scanner sc = new Scanner(System.in);
System.out.print("用户名:");
String loginName = sc.next();
System.out.print("密码:");
String loginPwd =sc.next();
return true;
}
/**
* 登录:手机验证码
* */
@Override
public boolean login(int phoneCode){
Scanner sc = new Scanner(System.in);
System.out.print("请输入手机验证码:");
int pc = sc.nextInt();
return true;
}
/**
* 登录:人脸识别
* */
@Override
public boolean login(String face){
System.out.print("请不要动,人脸识别中...");
return true;
}
}
//考试系统
public class ExamSys {
public static void main(String[] args) {
init();
}
public static void init() {
System.out.println("******************黑马考试系统******************");
System.out.println("请选择学科: 1) Java \t 2) UI");
int subjectNumber = new Scanner(System.in).nextInt();
switch (subjectNumber) {
case 1:
JavaStudent javaStu = new JavaStudent();
//考试前:先登录
if (login(javaStu)) {
System.out.println("登录成功!");
//多态的体现:传递的是子类对象
startExam(javaStu);
}
break;
case 2:
UiStudent uiStu = new UiStudent();
if (login(uiStu)) {
System.out.println("登录成功!");
//多态的体现:传递的是子类对象
startExam(uiStu);
}
break;
default:
System.out.println("选择错误,退出系统!");
System.exit(0);
}
}
//登录
public static boolean login(Student stu) {
System.out.println("---------------------------------------------");
System.out.println("请选择登录方式:");
System.out.println("1、用户名/密码");
System.out.println("2、手机验证码");
System.out.println("3、人脸识别");
int loginNumber = new Scanner(System.in).nextInt();
System.out.println("---------------------------------------------");
boolean result = false;
switch (loginNumber) {
case 1:
result = stu.login("用户名", "密码");
break;
case 2:
result = stu.login(40088);
break;
case 3:
result = stu.login("人脸数据");
break;
}
return result;
}
/**
* 开始考试
* @param stu 父类引用作为形参
*/
public static void startExam(Student stu) {
System.out.println("*****************考试题****************");
stu.exam();
}
}
小结
动态多态的书写方式: 父类 父对象 = new 子类();
动态多态在开发中的应用场景:
-
方法中参数多态
-
方法返回值多态
-
//返回值多态 //返回类型为:Student类型(父类型) public Student createObject(int flag , String name,int age){ if(flag ==1){ //实例化子类对象 return new JavaStudent(name,age);//返回子类对象 }else if (flag ==2 ){ return new UiStudent(name,age); } }
-
多态的好处:提高程序中代码的复用性、扩展性
05_多态:多态中方法的执行特点(了解)
目标
- 能够理解在多态中方法执行特点
路径
- 成员方法在多态中的执行特点
- 代码验证
说明:
成员变量不参与多态,只有成员方法才有多态现象
成员方法在多态中的执行特点
- 多态的格式调用方法,指的是使用父类型调用方法
- 方法执行时,会执行子类重写的方法
- 如果子类没有重写方法,会向父类找到方法执行
- 前提:父类中不是抽象方法(父类的方法有具体的代码实现)
- 使用多态形式调用方法,不能调用子类中特有的方法(多态的弊端)
结论:在多态中,父引用只能调用子类和父类中共有的方法
- 父引用 可以调用父类自己的方法
案例代码(验证多态中方法的特点)
public class JavaStudent extends Student { public JavaStudent() { } public JavaStudent(String number, String name, int age, String classes) { super(number, name, age, classes); } @Override public void exam() { System.out.println("-----------------------------------------------------"); System.out.println("java学生,在进行阶段考试!"); } //子类特有的功能 public void project(){ System.out.println("java学生,在紧张的进行项目实践....."); } }
public static void startExam(Student stu){
System.out.println("******************XXXXX学科考试题***************");
//不同对象的相同行为
stu.exam();//调用不同学生对象中的考试方法
//stu.project();//父类对象不能调用子类中特有的方法
System.out.println("--------------------------------------------------");
}
小结
- 多态中父引用调用的方法,是指父类中的方法
- 在多态中会检查 父类中的方法是否存在,不存在时:报错
- 多态调用方法时:
- 子类重写了父类中的方法,执行重写后的方法
- 子类没有重写父类中的方法,执行时会去父类中找相关方法执行
- 多态的弊端
- 父引用无法调用子类中特有的方法
06_多态:多态的类型转换
目标
- 掌握引用数据类型的向下转型方式
路径
- 向上转型
- 向下转型
前言
在学习基本数据类型时,有讲过一个知识点:基本数据类型转换
- 隐式转换:小类型自动转换为大类型(不需要书写代码)
- 强制转换:大类型强制转换为小类型(需要手动书写代码)
- 格式:小类型 变量 = (小类型) (大类型数据)
引用类型:数组、String、类、接口
引用类型的转换:
- 向上转型(小类型转大类型)【自动完成,不需要书写代码】
- 向下转型(大类型转小类型)
向上转型
在书写多态代码时,就已经实现向上转型
Student stu = new UiStudent();//UiStudent类型转换为Student类型(类型提升)
注意:stu引用的是子类对象,虽然类型向上转型了,但底层实际还是子类
向下转型
多态的弊端:父引用无法调用子类特有的方法
- 解决方案:使用多态的向下转型
向下转型的书写格式: 子类 子类对象 = (子类) 父引用
//多态体现:向上转型
Student stu = new JavaStudent();
stu.project("");//父类对象无法调用子类中特有方法
//访问JavaStudent类中的特有方法
JavaStudent javaStu = (JavaStudent) stu; //向下转型:把父类型转换为子类类型
javaStu.project("黑马考试系统");
小结
在使用多态时,存在着引用类型的转换:
-
向上转型: 父引用指向子类对象时(子类类型自动转换为父类类型)
- 弊端:父引用无法调用子类中的特有方法
-
向下转型:把父类类型强制转换为子类类型
- 书写格式: 子类 子类对象 = (子类) 父引用
07_多态:instanceof关键字
目标
- 掌握instanceof关键字的使用
路径
- 向下转型时会发生的异常问题
- 使用关键字instanceof解决转型时的异常问题
- 案例:instanceof的应用
向下转型时出现的异常问题
异常:java.lang.ClassCastException
发生异常的原因:把子类类型转换为另一种子类类型时(类型不匹配)
使用关键字instanceof避免ClassCastException异常
书写格式:
if(对象名 instanceof 数据类型){
//instanceof关键字的作用:判断指定的对象是否为某种类型
}
Student stu = new JavaStudent();
if( stu instanceof JavaStudent ) //检查stu对象底层是否为JavaStudent类型
{
JavaStudent javaStu = (JavaStudent) stu;
javaStu.setProject("黑马考试系统");
}else if( stu instanceof UiStudent ){
UiStudent uiStu = (UiStudent) stu;
uiStu.setOpus("茶具设计");
}
案例:改造"考试系统"中的开始考试功能
public static void startExam(Student stu) {
String subject = "";
if (stu instanceof JavaStudent) {
subject = "Java学科";
} else if (stu instanceof UiStudent) {
subject = "UI学科";
}
System.out.println("*****************" + subject + "考试题****************");
stu.exam();
}
小结
instanceof关键字的作用:
- 可以判断对象的类型
应用场景:
- 可以根据不同的对象类型,来执行不同的功能
- 可以避免多态中的向下转换时出现的ClassCaseException异常
二、权限和final关键字
08_关键字:权限修饰符
目标
- 了解java中四种访问权限的特点
路径
- 访问权限修饰符
访问权限修饰符(关键字)
权限关键字:
- public,公开的 【没有底限,可以任意访问】
- private,私有的 【最小的访问范围:在本类中】
- 默认的 (在代码上不书写任何关键字)
- protected , 受保护的(专为子类提供的)
访问权限从小到大排序: private < 默认的 < protected < public
public | protected | 默认的 | private | |
---|---|---|---|---|
同一类中 | √ | √ | √ | √ |
同一包中的子类 | √ | √ | √ | |
同一包中的无关类(非子类) | √ | √ | √ | |
不同包的子类 | √ | √ | ||
不同包中的无关类(非子类) | √ |
结论:public具有最大权限。private则是最小权限
默认的访问范围只认同一个包下
protected访问范围只认子类(同一个包也可以)
建议:
- 通常在开发中,如没有特殊需求,属性全部设置为private,方法都设置为public
小结
从大到小排列访问权限:public 、protected、默认的、private
09_关键字:final
目标
- 掌握final修饰符的不同应用
路径
- final修饰符的介绍
- final修饰符的应用场景
final修饰符
final的含义:最终的、不可改变的
在java语言中,使用final可以用来修饰:类、变量、方法
格式:
//修饰类
public final class Student{
}
//修饰方法
public final void method(){
}
//修饰变量
private final String name="小明";
final在开发中的应用场景
-
当定义常量时:
-
变量添加final修饰符后,变量成为了常量
-
常量的值只能赋值一次
-
final int number = 10; //后续无法再修改number的值 number=100;//报错
-
-
当类中的方法不能被子类重写时
-
在方法是添加final修饰符(方法不能重写)
-
class Father{ //不可以改变的方法(不能被子类重写) public final void method(){ } } //子类 继承父类 class Son extends Father{ //子类无法对Father类中的method进行重写 }
-
-
不希望类被继承时
-
在类上添加final修饰符(类不能被继承)
-
final class Father{ //类不能被继承 } //报错:Father类不能被继承 class Son extends Father{}
-
小结
- final修饰符号,可以用来修饰:类、方法、变量
- final修饰类,类不能被继承
- final修饰方法,方法不能被重写
- final修饰变量,变量成为了常量,初始化值之后无法修改常量的值
三、接口
10_接口:接口的定义
目标
- 掌握接口的定义方式
路径
- 接口的介绍
- 接口的定义
- 接口中的成员
接口的介绍
接口,是java语言中的一种引用类型。 已经学习过的引用类型:数组、类、String、集合
接口,和类属于同一级别的
接口,可以理解为是方法的集合体(接口中通常就是用定义方法的)
- 接口中封装的就是抽象方法(JDK1.7之前)
- 从JDK1.8开始,接口中增加了:静态方法、默认方法
- 从JDK1.9开始,接口中增加了:私有方法
接口,不能实例化(不能创建对象)【接口中没有构造方法】
接口的定义
定义类:
class HelloWorld{
//成员变量
//成员方法
//构造方法
}
定义接口: 使用关键字interface
interface Hello{
//接口中的成员
}
接口中的成员
JDK1.8之前的接口中只能定义两个成员:抽象方法、静态常量(在后面内容中介绍)
JDK1.8添加了:静态方法、默认方法
JDK1.9添加了:私有方法
//接口名的命名方式:大驼峰
public interface HelloInter{
//静态常量
public static final int NUMBER=100; //常量名通常全大写
//抽象方法
public abstract void method();
}
//JDK1.8:
public interface HelloInter{
//静态常量
//抽象方法
//默认方法
public default int addNum(int n){
return n + 1;
}
//静态方法
public static void method(){
}
}
//JDK1.9
public interface HelloInter{
//静态常量
//抽象方法
//默认方法
//静态方法
//新增:私有方法
private boolean isOpen(){
return false;
}
}
小结
接口的定义方式:interface 接口名{ … }
接口中可以书写的内容:
- 静态常量
- 抽象方法
- 静态方法
- 默认方法
- 私有方法
11_接口:接口的基本使用
目标
- 能够使用implements关键字实现接口
路径
- 实现接口的书写方式
- 接口中的抽象方法
实现接口的格式
定义接口:
interface Hello{
//常量
public static final int NUMBER=100;
//抽象方法
public abstract void method(int num);
}
在java中接口不能实例化,需要定义一个子类来实现(继承)接口,通过实例化子类对象,来访问接口的成员
子类实现接口,使用关键字:implements
//子类 实现 接口
class Child implements Hello{
//重写抽象方法
public void method(int num){
//方法体代码
}
}
接口中的抽象方法
在子类实现接口之后,必须对接口中的抽象方法进行重写
class Child implements Hello{
//重写抽象方法
public void method(int num){
//方法体代码
}
}
//实例化子类对象
Child c = new Child(); //使用对象本身类型来定义
c.method(); //调用重写后的方法
//多态的体现
Hello h = new Child();//使用对象的父类型来定义
h.method(); //调用重写后的方法
//多态:
父类/父接口 父引用 = new 子类();
List list = new ArrayList()
小结
定义接口使用:interface
public interface 接口名{
//静态常量
//抽象方法
}
实现接口使用:implements
public class 实现类 implements 接口{
//重写接口中的所有的抽象方法
}
使用接口中的功能:
//实例化子类
子类 对象 = new 子类();
//多态:
接口 对象 = new 子类();
12_接口:接口的应用案例
目标
- 使用接口改造"考试系统"中的登录功能
路径
- 分析案例中存在的问题
- 代码实现
分析案例中的问题
//父类
public abstract class Student {
//省略成员变量
//省略构造方法
//登录
public abstract boolean login(String name,String passwd);
public abstract boolean login(int phoneCode);
public abstract boolean login(String face);
//省略getter()、setter()
}
//子类
public class JavaStudent extends Student{
//登录:用户名和密码
@Override
public boolean login(String name,String passwd){
Scanner sc = new Scanner(System.in);
System.out.print("用户名:");
String loginName = sc.next();
System.out.print("密码:");
String loginPwd =sc.next();
return true;
}
//登录:手机验证码
@Override
public boolean login(int phoneCode){
Scanner sc = new Scanner(System.in);
System.out.print("请输入手机验证码:");
int pc = sc.nextInt();
return true;
}
//登录:人脸识别
@Override
public boolean login(String face){
System.out.print("请不要动,人脸识别中...");
return true;
}
}
思考:当程序中再增加一种新的登录方式"微信登录",程序代码怎么修改?
//修改父类代码
public abstract Student{
//登录
public abstract boolean login(String name,String passwd);
public abstract boolean login(int phoneCode);
public abstract boolean login(String face);
//新增:
public abstract boolean login(WeiXin weixin)
}
//修改子类代码
public class JavaStudent extends Student{
//登录1:用户名、密码
//登录2:手机验证码
//登录3:人脸识别
//新增登录4: 微信登录
public boolean login(WeiXin weixin){
//........
}
}
分析出的问题:
1、随着新的登录功能的添加,父类和子类中的代码会越来越多
2、企业中开发的思想:尽量避免修改原有类中的代码
3、现有案例"黑马考试系统"中,程序代码的复用性并不强、扩展性不强
解决方案:使用接口改造代码
接口作用:
1、用来定义标准
代码实现
//定义接口:登录适配器接口
public interface ILoginAdapter {
public boolean login();
}
//账号登录
public class AccoutLogin implements ILoginAdapter {
@Override
public boolean login() {
return account();
}
public boolean account(){
Scanner sc = new Scanner(System.in);
System.out.print("用户名:");
String loginName = sc.next();
System.out.print("密码:");
String loginPwd =sc.next();
return true;
}
}
//父类:Student
public abstract class Student {
private String number;//学号
private String name;//姓名
private int age;//年龄
private String classes;//班级
public Student() {
}
public Student(String number, String name, int age, String classes) {
this.number = number;
this.name = name;
this.age = age;
this.classes = classes;
}
//考试
public abstract void exam();
/**
* 登录
* @param loginAdapter 登录适配器接口 作为形参
* @return 登录结果
*/
public abstract boolean login(ILoginAdapter loginAdapter);
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
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;
}
public String getClasses() {
return classes;
}
public void setClasses(String classes) {
this.classes = classes;
}
}
//子类:JavaStudent
public class JavaStudent extends Student{
public JavaStudent() {
}
public JavaStudent(String number, String name, int age, String classes) {
super(number, name, age, classes);
}
/**
* 考试
*/
@Override
public void exam() {
System.out.println("Java学生,进行阶段性考试!");
}
/**
* 登录
*/
@Override
public boolean login(ILoginAdapter loginAdapter) {
//多态的体现:根据传递的不同对象,调用不同的登录
return loginAdapter.login();
}
}
//考试系统
public class ExamSys {
public static void main(String[] args) {
init();
}
public static void init() {
System.out.println("******************黑马考试系统******************");
System.out.println("请选择学科: 1) Java \t 2) UI");
int subjectNumber = new Scanner(System.in).nextInt();
switch (subjectNumber) {
case 1:
JavaStudent javaStu = new JavaStudent();
//考试前:先登录
if (login(javaStu)) {
System.out.println("登录成功!");
startExam(javaStu);
}
break;
case 2:
UiStudent uiStu = new UiStudent();
if (login(uiStu)) {
startExam(uiStu);
}
break;
default:
System.out.println("选择错误,退出系统!");
System.exit(0);
}
}
//登录
public static boolean login(Student stu) {
System.out.println("---------------------------------------------");
System.out.println("请选择登录方式:");
System.out.println("1、用户名/密码");
System.out.println("2、手机验证码");
System.out.println("3、人脸识别");
int loginNumber = new Scanner(System.in).nextInt();
System.out.println("---------------------------------------------");
boolean result = false;
switch (loginNumber) {
case 1:
//多态的体现:子类对象作为实参
result = stu.login( new AccoutLogin() );
break;
case 2:
result = stu.login(new ValidateCodeLogin());
break;
case 3:
//
break;
}
return result;
}
//开始考试
public static void startExam(Student stu) {
String subject = "";
if (stu instanceof JavaStudent) {
subject = "Java学科";
} else if (stu instanceof UiStudent) {
subject = "UI学科";
}
System.out.println("*****************" + subject + "考试题****************");
stu.exam();
}
}
13_接口:接口的多实现和多继承
目标
- 掌握接口的多实现和多继承的书写
路径
- 接口多实现的书写方式
- 接口多继承的书写格式
- 继承类的同时接口多实现格式
接口的多实现
类和类之间是什么关系?
- 继承关系
类和接口之间是什么关系?
- 实现关系
一个类可以继承多个父类吗?
- 不可以。 类只能单一继承
一个类可以实现多个接口吗?
- 可以
接口作用:
- 解决类只能单一继承的问题(接口的多实现)
类实现多个接口的格式:
interface InterA{
public abstract void method1();
}
interface InterB{
public abstract void method2();
}
interface InterC{
public abstract void method3();
}
//子类实现多个接口 多个接口之间使用逗号分隔
class Child implements InterA,InterB,InterC{
//子类中需要把所接口中的抽象方法全部重写
}
疑问:如果多个接口中存在相同的抽象方法时,子类实现接口时怎么办?
答案:针对相同的抽象方法,子类只需要重写1次
interface InterA{
public abstract void method();
}
interface InterB{
public abstract void method();
}
interface InterC{
public abstract void method();
}
//子类
class Child implements InterA,InterB,InterC{
//父接口中相同的抽象方法,子类只需要重写一次
public void method(){
}
}
接口的多继承
类和类之间是:继承
类和接口之间是:实现
接口和接口之间是:继承
interface InterA{
public abstract void method();
}
interface InterB{
public abstract void show();
}
//子接口 接口之间允许多继承
interface MyInter extends InterA,InterB{
//当前的子接口中具有:method、show两个抽象方法
}
class Child implements MyInter{
//重写:method、show方法
}
继承父类的同时进行接口的多实现
class Child extends 父类 implements 接口1,接口2,接口3{
//重写所有接口中的抽象方法
//假设父类为抽象类时,重写抽象类中的抽象方法
}
小结
接口的多实现:
public class 子类 implements 接口1,接口2,接口3,.......{
}
接口的多继承:
public interface 子接口 extends 接口1,接口2,....{
}
子类继承父类的同时,也实现接口:
public 子类 extends 父类 implements 接口1,接口2,...{
}
14_接口:接口和抽象类的区别
目标
- 了解接口和抽象类在应用上的区别
路径
- 接口和抽象类的区别
接口和抽象的区别
抽象类:
- 用来封装事物的属性、行为
- 抽象类中有:成员变量、成员方法(静态方法、私有方法)、构造方法、抽象方法
- 抽象类不能实例化,是由子类实例化后使用的
- 子类只能继承一个抽象类(单一继承)
- 抽象类通常是描述一个事物
接口:
- 用来封装行为
- 接口中有:静态常量、抽象方法、静态方法、默认方法、私有方法
- 接口不能实例化,是由子类实例化后使用
- 子类可以实现多个接口(多实现)
- 接口通常是用来制定标准 (后面学习的课程中还会遇到很多。例:JDBC)