之前研究了两天Android的MVP架构,感觉先理解了接口更容易理解,所以先说一下接口相关的知识:
简单的举个老师、学生和四项家庭作业的栗子!
过程:老师留了听、说、读、写四门没有统一正确标准的作业(四个interface类)要求学生自己做(A和B都要implantment四个接口),学生做了各自认为是正确的答案,第二天老师检查答案。这个时候老师需要指定学生,然后检查该学生的听、说、读、写,结果输出一下。
先看一下目录结构图:
定义了四个接口四个接口代表四个行为,分别让学生来来实现,截图如下:
IListen
IRead:
ISpeek:
IWrite:
学生A的代码:打印A自己的答案
<span style="font-size:18px;">package student;
import interfaces.IListen;
import interfaces.IRead;
import interfaces.ISpeek;
import interfaces.IWrite;
public class StudentA implements IListen,ISpeek,IRead,IWrite{
public void listenRedio() {
// TODO Auto-generated method stub
System.out.println("RadioA");
}
public void writePoem() {
// TODO Auto-generated method stub
System.out.println("PoemA");
}
public void readSomething() {
// TODO Auto-generated method stub
System.out.println("somethingA");
}
public void speekHanyu() {
// TODO Auto-generated method stub
System.out.println("啊");
}
}</span>
学生B代码:打印B自己的答案
<span style="font-size:18px;">package student;
import interfaces.IListen;
import interfaces.IRead;
import interfaces.ISpeek;
import interfaces.IWrite;
public class StudentB implements IListen,ISpeek,IRead,IWrite{
public void listenRedio() {
// TODO Auto-generated method stub
System.out.println("RadioB");
}
public void writePoem() {
// TODO Auto-generated method stub
System.out.println("PoemB");
}
public void readSomething() {
// TODO Auto-generated method stub
System.out.println("somethingB");
}
public void speekHanyu() {
// TODO Auto-generated method stub
System.out.println("波");
}
}</span>
老师代码:start()方法表示老师对每个学生的操作都是一样的,打印收到的四个结果
<span style="font-size:18px;">package test;
import student.StudentA;
import student.StudentB;
import interfaces.IListen;
import interfaces.IRead;
import interfaces.ISpeek;
import interfaces.IWrite;
public class Teacher {
//定义四个接口的示例
IListen listen = null;
IRead read = null;
ISpeek speek = null;
IWrite write = null;
//打印四个实例对应的内容,就扣调用操作
void start(){
listen.listenRedio();
read.readSomething();
speek.speekHanyu();
write.writePoem();
}
//将StudentA的四项作业结果交给老师
void checkA(){
listen = new StudentA();//在这里我们能看到,StudentA因为实现了四个接口,所以他可以被看作是任意一个接口的实例。
read = new StudentA(); //这里也是JAVA的重要的知识点,向上转型(因该是向上,这个很重要,我自己明白,具体说不清,见谅)
speek = new StudentA(); //这里用到的就是接口什么多态、上下转型一堆原理
write = new StudentA();
}
//将StudentB的四项作业结果交给老师
void checkB(){
listen = new StudentB();//和A的情况差不多
read = new StudentB();
speek = new StudentB();
write = new StudentB();
}
public static void main(String[] args) {
Teacher teacher = new Teacher();
teacher.checkA();//检查A,所有接口指向A
teacher.start();
System.out.println("===============");
teacher.checkB();//检查B,所有接口指向B
teacher.start();
}
}</span>
运行截图:
可以明显的看出双线上下的内容是不一样的,分别是每个学生自己的内容。
这里的逻辑并不是通常的那样,通常来说可能是:学生A,你出来,我要检查你的作业,你把听、说、读、写都给我看看!
这里应该是这样的:第二天老师说:我要检查IListen的作业,那么好,谁做了IListen老师就可以找谁,找到了A,A说我听了ReadioA(因为这里方法的调用者是IListen不是studentA)。
当然,以上代码可以进化一下,在student包中提供一个虚类student 实现四个接口,然后由学生继承虚类:
package student;
import interfaces.IListen;
import interfaces.IRead;
import interfaces.ISpeek;
import interfaces.IWrite;
public abstract class Student implements IListen,ISpeek,IRead,IWrite{
//加一个说明自己是谁的方法
public abstract void who();//因为会挎包调用,需要声明public,默认是protected
}
学生的代码相应的必须加上自我介绍的方法,A、B基本类似,只看A的代码如下:
package student;
public class StudentA extends Student{
public void listenRedio() {
// TODO Auto-generated method stub
System.out.println("RadioA");
}
public void writePoem() {
// TODO Auto-generated method stub
System.out.println("PoemA");
}
public void readSomething() {
// TODO Auto-generated method stub
System.out.println("somethingA");
}
public void speekHanyu() {
// TODO Auto-generated method stub
System.out.println("啊");
}
//这里就是新加的自我介绍 方法
void who() {
System.out.println("我是学生A");
}
}
package test;
import student.Student;
import student.StudentA;
import student.StudentB;
import interfaces.IListen;
import interfaces.IRead;
import interfaces.ISpeek;
import interfaces.IWrite;
public class Teacher {
//定义四个接口的示例
IListen listen = null;
IRead read = null;
ISpeek speek = null;
IWrite write = null;
//打印四个实例对应的内容,就扣调用操作
void start(){
listen.listenRedio();
read.readSomething();
speek.speekHanyu();
write.writePoem();
}
//将StudentA的四个内容交给接口,根据作业条学生查,下面B同理
void checkA(){
listen = new StudentA();
read = new StudentA();
speek = new StudentA();
write = new StudentA();
}
void checkB(){
listen = new StudentB();
read = new StudentB();
speek = new StudentB();
write = new StudentB();
}
//根据学生查作业
void checkByStudent(Student student){
student.who();
student.listenRedio();
student.speekHanyu();
student.readSomething();
student.writePoem();
}
public static void main(String[] args) {
Teacher teacher = new Teacher();
teacher.checkA();
teacher.start();
System.out.println("===============");
teacher.checkB();
teacher.start();
//大型分割线
System.out.println("******************");
System.out.println("******************");
//检查学生A和B
teacher.checkByStudent(new StudentA());
System.out.println("===============");
teacher.checkByStudent(new StudentB());
}
}
再贴上来运行结果图:
从这里基本可以看出,一个类的方法如果定义在接口中,就可以通过该接口实例化该类,调用他的具体是实现内容。凡是继承过的接口、虚类都可以来声明某个类,而且这样的声明只能调用到自己定义的,无权干涉其他的(你要是自定义的方法内部调用了,那算我没说!)。
其实这里就是想说明多态,上下转型这些的方便性,不知道有没有说清,先就这样了