接口
信息管理系统优化(更换容器)
- 改进点
我们需要将容器修改成集合,而在我们的分类思想中Dao类才是需要和数据进行交互的,所以其实我们只需要修改Dao类就可以了。在新的Dao中所提供的类的名称和之前一致即可(如果不一致则影响Service类的调用) - 我们的修改遵循开闭原则,不更改原来的代码类
这次我们的根据开闭原则新创建了一个OtherStudentDao类,注意:我们不要修改OtherStudentDao类中任何方法的定义,如果我们修改了OtherStudentDao中方法的定义,可能会导致StudentServiece和Control类中相应的方法也需要改变(因为Serviece类会调用Dao中相应的方法)
信息管理系统----抽取公共Dao
- 存在的问题
- 1.StudentDa和OtherStudentDao类有相同的部分,可以提取成一个父类
- 2.因为父类中的方法无法具体描述所以写成一个抽象类
- 父类
package com.itheima.edu.info.manager.dao;
import com.itheima.edu.info.manager.domain.Student;
import java.util.ArrayList;
//dao包库管,对数据进行操作
public abstract class BaseStudentDao {
public abstract boolean addStudent(Student student) ;
public abstract Student[] findAllStudent() ;
public abstract void deleteStudentById(String id) ;
//通过id找到他在数组中的索引
public abstract int getIndex(String id);
public abstract void updateStudent(String id, Student student);
}
- 子类
package com.itheima.edu.info.manager.dao;
import com.itheima.edu.info.manager.domain.Student;
//dao包库管,对数据进行操作
public class StudentDao extends BaseStudentDao {
//创建Student学生数组长度为5
private static Student[] students = new Student[5];
//静态代码块初始化学生数据
static {
Student s1 = new Student("001", "张三", 18, "1990-01-01");
Student s2 = new Student("002", "李四", 23, "1937-03-01");
students[0] = s1;
students[1] = s2;
}
@Override
public boolean addStudent(Student student) {
//2.将接收到的学生对象添加到数组中
//2.1定义遍历index=-1
int index = -1;
//2.2遍历数组中的每一个元素,判断是否为null
for (int i = 0; i < students.length; i++) {
if (students[i] == null) {
index = i;
break;
}
}
//3.返回是否添加成功
if (index == -1) {
//装满了
return false;
} else {
//没有装满,正常添加,返回true
students[index] = student;
return true;
}
}
@Override
public Student[] findAllStudent() {
//返回我们创建的对象数组
return students;
}
@Override
public void deleteStudentById(String id) {
//1.找到该id在数组中对应的索引
int index = getIndex(id);
//2.将该索引的对象使用null替代
students[index] = null;
}
//通过id找到他在数组中的索引
@Override
public int getIndex(String id){
int index=-1;//记录id对应索引的的位置
for (int i = 0; i < students.length; i++) {
if(students[i]!=null&&id.equals(students[i].getId())){
index=i;
break;
}
}
return index;
}
@Override
public void updateStudent(String id, Student student) {
//1.查找id在容器中的索引
int index = getIndex(id);
//2.将该索引的位置,使用新的学生对象替换
students[index] = student;
}
}
package com.itheima.edu.info.manager.dao;
import com.itheima.edu.info.manager.domain.Student;
import java.util.ArrayList;
//dao包库管,对数据进行操作
public class OtherStudentDao extends BaseStudentDao {
//使用集合作为容器
//private static Student[] students = new Student[5];
private static ArrayList<Student> students = new ArrayList<>();
//静态代码块初始化学生数据
static {
Student s1 = new Student("001", "张三", 18, "1990-01-01");
Student s2 = new Student("002", "李四", 23, "1937-03-01");
students.add(s1);
students.add(s2);
}
@Override
public boolean addStudent(Student student) {
//因为集合装不满,所以不需要进行判断,直接添加即可
students.add(student);
return true;
}
@Override
public Student[] findAllStudent() {
//1.我们可以选择返回数组或者即可
//2.返回集合将会修改Service和Controller中的代码,我们选择返回数组
//3.然后将集合中的元素全部装回数组中
Student[] stu = new Student[students.size()];//数组的长度和集合长度保持一致
stu =students.toArray(stu);//将集合变成数组返回
return stu;
}
@Override
public void deleteStudentById(String id) {
//1.找到该id在数组中对应的索引
int index = getIndex(id);
//2.将该索引的对象使用null替代
students.remove(index);
}
//通过id找到他在数组中的索引
@Override
public int getIndex(String id){//(改为遍历集合即可)
int index=-1;//记录id对应索引的的位置
for (int i = 0; i < students.size(); i++) {
if(students.get(i)!=null&&id.equals(students.get(i).getId())){
index=i;
break;
}
}
return index;
}
@Override
public void updateStudent(String id, Student student) {
//1.查找id在容器中的索引
int index = getIndex(id);
//2.将该索引的位置,使用新的学生对象替换
students.set(index, student);
}
}
在这次优化中,我们是先有子类,然后才抽取成父类,这样好像看不出什么好处。但是我们可以先定义抽象父类(制定模板),然后子类继承模板,然后只需要完成模板的内容即可,这样我们编写代码更简便
接口的介绍
- 存在问题
- 接口定义
接口的定义和特点
接口实现类的命名规则:
- 如接口Inter
- 实现类 InterImpl
前半部分往往是接口的名字,后半部分是Implements的缩写(Impl) - 重点
1.和继承相比,接口可以进行多继承,拓展性更强
2.多实现接口不会和多继承一样存在逻辑冲突吗?
不会存在逻辑冲突。多继承中当多个父类存在相同的方法时,子类在调用的时候会存在不知道调用那个的问题
而如果多个接口中存在相同的抽象方法需要实现,因为接口中都是抽象方法,不存在具体逻辑,子类只用实现其中的一个即可
接口中成员的特点
- 注意点:
1.系统默认给接口中成员添加public static final(所以一定是常量)
2.接口中没有构造方法,所以子类中的构造方法默认super()访问的是object中的构造方法
3.接口中的方法自动添加 public abstract(默认为抽象方法) - 总结
JDK8版本中成员的特点---默认方法
-
原有接口存在的问题
安装原来的标准来说:我们需要在接口中添加方法,而且只能是抽象方法。此时我们的所以实现类必须抽象新添加的方法。如果不重写,我们所有的实现类都会报错 -
解决方法
-
JDK8成员方法的特点
1.接口中的默认方法可以被子类重写,但是 不需要添加default关键字 -
2.默认方法的权限默认使用public(不写系统会自动添加)
3.当实现类实现多个接口,而多个接口有相同定义的默认方法,此时调用默认方法,java会怎样应对?
这样又回到了之前的逻辑问题,为了解决这样的逻辑冲突问题,java则执行:实现类必须要重写多个相同的默认方法的策略,然后调用的时候则是调用自己重写的方法(不知道调用哪一个,则调用自己实现的) -
注意事项
JDK8版本中接口成员的特点--静态方法
- 注意点
1.接口中定义的静态方法只能通过接口名进行调用(实现类对象无法调用)
2.接口中静态方法权限默认为public,如果不写系统默认帮我们添加
3.接口中静态方法的调用不存在逻辑冲突问题(多个接口中定义相同的静态方法)
因为接口中的静态方法只能通过接口名进行调用,可以通过不同的接口名区分调用的方法
- 注意事项
JDK9版本中接口成员的特点---private方法
-
存在场景
-
定义格式
如果在接口中的方法是不需要外界进行访问就可以考虑定义为私有方法 -
接口使用思路总结
类和接口的关系
- 一个细节
当一个接口A继承了多个接口,而多个接口中有相同的默认方法。此时接口A不知道继承哪个接口。此时的接口A方案是在接口中重写这个方法,并使用自己重写的方法
信息管理系统---接口优化
- 改进点
我们重上面抽象类的优化中可以看出此时我们的抽象父类所有的方法都是抽象方法,此时正好符合接口的定义,故可以进一步优化