目录
接口
认识接口
接口的好处
接口的综合案例
需求
学生类
班级管理类
学生操作接口
学生操作类
完善班级管理类
测试
接口
认识接口
- Java提供了一个关键字 interface,用这个关键字我们可以定义出一个特殊的结构:接口。
public interface 接口名{
//成员变量(常量)
//成员方法(抽象方法)
}
在接口中,不需要将变量用final修饰成常量,它会自动转为常量,例如:
public interface A{
double R = 3.14;
//相当于 public static final double r = 3.14;
}
注意:常量建议使用大写来命名。
方法也同样,接口会自动将方法转为抽象方法,例如:
public interface A{
void run();
//相当于public abstract void run();
}
故而接口中的方法只能有签名,不能有方法体。
注意:接口不能创建对象;接口是用来被类实现(implements)的,实现接口的类称为实现类。
修饰符 class 实现类 implements 接口1,接口2,接口3,...{
}
- 一个类可以实现多个接口(接口可以理解成干爹),实现类实现多个接口,必须重写完全部接口的全部抽象方法,否则实现类需要定义成抽象类。
接口的好处
- 弥补了类单继承的不足,一个类同时可以实现多个接口。
- 让程序可以面向接口编程,这样程序员就可以灵活方便的切换各种业务实现。
例如下面这种情况,一个类继承了几个类之后就不能再继承其他类了,这时需要其他功能就可以用接口来实现了。
public class Test{
public static void main(String[] args){
Student s = new A();
}
}
class Student{
}
class A extends Student{
}
接口为其拓展更多功能:
public class Test{
public static void main(String[] args){
Singer s = new A(); //或是 Driver s = new A();
}
}
class A extends Student implements Driver,Singer{
@override
public void drive{
}
@override
public void sing{
}
}
class Student{
}
interface Driver{
void drive();
}
interface Singer{
void sing();
}
1.使用接口有啥好处,第一个好处是什么?
- 可以解决类单继承的问题,通过接口,我们可以让一个类有一个亲爹的同时,还可以找多个干爹去扩展自己的功能。
2.为什么我们要通过接口,也就是去找干爹,来扩展自己的功能呢?
- 因为通过接口去找干爹,别人通过implements的接口,就可以显性地知道你是谁,从而也就可以放心地把你当作谁来用了。
3.使用接口的第二个好处是什么?
- 一个类我们说可以实现多个接口,同样,一个接口也可以被多个类实现。这样做的好处是我们的程序就可以面相接口编程了,这样我们程序员就可以很方便的灵活切换各种业务实现了。
接口的综合案例
需求
请设计一个班级学生的信息管理模块:学生的数据有:姓名、性别、成绩
功能1:要求打印出全班学生的信息;
功能2:要求打印出全班学生的平均成绩。
注意!以上功能的业务实现是有多套方案的,比如:
- 第1套方案:能打印出班级全部学生的信息;能打印班级全部学生的平均分。
- 第2套方案:能打印出班级全部学生的信息(包含男女人数);能打印班级全部学生的平均分(要求是去掉最高分、最低分)
要求:系统可以支持灵活的切换这些实现方案。
先定义出基本的学生类:
学生类
package user.interfaceDemo;
public class Student {
private String name;
private char sex;
private double score;
public Student() {
}
public Student(String name, char sex, double score) {
this.name = name;
this.sex = sex;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
}
因为我们要设计班级学生的信息管理模块,所以接下来把班级管理类定义出来,其中有包含学生的班级集合以及班级里面的学生信息。
班级管理类
package user.interfaceDemo;
import java.util.ArrayList;
public class ClassManager {
private ArrayList<Student> students = new ArrayList<>();
//构造器初始化出班级内部的信息
public ClassManager(){
students.add(new Student("余周周",'女',99));
students.add(new Student("林杨",'男',100));
students.add(new Student("蒋川",'男',80));
students.add(new Student("凌翔茜",'女',90));
}
//打印出全班学生的信息
public void printInfo(){
}
//打印出全班学生的平均成绩
public void printScore(){
}
}
实现的方法这部分因为要能够灵活切换,所以需要用接口实现,先空着,去定义接口。
学生操作接口
package user.interfaceDemo;
import java.util.ArrayList;
public interface StudentOperator {
void printAllInfo(ArrayList<Student> students);
void printAverageScore(ArrayList<Student> students);
}
下面就定义两个学生操作类,在学生操作类中去实现学生操作接口,分别重写接口的两个方法。
学生操作类
第一套方案:
package user.interfaceDemo;
import java.util.ArrayList;
public class StudentOperatorImp1 implements StudentOperator{
@Override
public void printAllInfo(ArrayList<Student> students) {
System.out.println("=======全班所有学生信息如下=======");
for (int i = 0; i < students.size(); i++) {
Student s = students.get(i);
System.out.println("姓名:" + s.getName());
System.out.println("性别:" + s.getSex());
System.out.println("分数:" + s.getScore());
if(i != students.size() - 1){
System.out.println("--------------------");
}
}
System.out.println("========================");
}
@Override
public void printAverageScore(ArrayList<Student> students) {
double allScore = 0.0;
for (int i = 0; i < students.size(); i++) {
Student s = students.get(i);
allScore += s.getScore();
}
System.out.println("该班级的平均分为:" + ( allScore / students.size() ));
}
}
第二套方案:
package user.interfaceDemo;
import java.util.ArrayList;
public class StudentOperatorImp2 implements StudentOperator{
@Override
public void printAllInfo(ArrayList<Student> students) {
System.out.println("=======全班所有学生信息如下=======");
int count1 = 0; //用于记录男生的数量
int count2 = 0; //用于记录女生的数量
for (int i = 0; i < students.size(); i++) {
Student s = students.get(i);
System.out.println("姓名:" + s.getName());
System.out.println("性别:" + s.getSex());
System.out.println("分数:" + s.getScore());
if(i != students.size() - 1){
System.out.println("--------------------");
}
if(s.getSex() == '男'){
count1++;
}else{
count2++;
}
}
System.out.println("男生人数为:" + count1 + "人");
System.out.println("女生人数为:" + count2 + "人");
System.out.println("班级总人数为:" + students.size() + "人");
System.out.println("========================");
}
@Override
public void printAverageScore(ArrayList<Student> students) {
double allScore = 0.0;
double max = students.get(0).getScore();
double min = students.get(0).getScore();
for (int i = 0; i < students.size(); i++) {
Student s = students.get(i);
if(s.getScore() > max) max = s.getScore();
if(s.getScore() < min) min = s.getScore();
allScore += s.getScore();
}
System.out.println("该班级的最高分是:" + max + "分");
System.out.println("该班级的最低分是:" + min + "分");
System.out.println("该班级的平均分为:" + ( (allScore - max - min) / (students.size() - 2) ));
}
}
接下来回到班级管理类,完善功能:
完善班级管理类
package user.interfaceDemo;
import java.util.ArrayList;
public class ClassManager {
private ArrayList<Student> students = new ArrayList<>();
//创建出学生操作对象,给下面的方法进行调用,其中StudentOperatorImp1可以替换为StudentOperatorImp2,功能就进行了变化.
private StudentOperator studentOperator = new StudentOperatorImp1();
//构造器初始化出班级内部的信息
public ClassManager(){
students.add(new Student("余周周",'女',99));
students.add(new Student("林杨",'男',100));
students.add(new Student("蒋川",'男',80));
students.add(new Student("凌翔茜",'女',90));
}
//打印出全班学生的信息
public void printInfo(){
studentOperator.printAllInfo(students);
}
//打印出全班学生的平均成绩
public void printScore(){
studentOperator.printAverageScore(students);
}
}
测试
package user.interfaceDemo;
public class Test {
public static void main(String[] args) {
ClassManager cc = new ClassManager();
cc.printInfo();
cc.printScore();
}
}
第一套方案的运行结果:
改为第二套方案:
第二套方案的运行结果为:
END
学习自:黑马程序员——JavaSE课程