1.接口变量
- 接口和类一样,是Java中的一种数据类型,用接口声明的变量称之为接口变量。
- 接口变量中存储的是实现了该接口的类的实例的引用。
- 接口回调借用了C语言中指针回调的术语。
2.接口回调 VS 指针回调
- 指针回调,表示一个变量的地址在某一时刻存放在一个指针变量 中,这个指针变量可以间接操作该变量中存放的数据;
- 接口回调,指的是可以把实现某一接口的类创建的对象的引用赋值给该接口声明的接口变量,那么该接口变量就可以调用被类实现的接口方法。(其实当接口变量在调用被类实现的接口方法时,就是在通知相应的对象调用这个方法)
- 接口变量无法调用类中其他的非接口方法。(类似于向上转型对象调用子类重写的方法)
例如:Com为接口,ImpleCom为实现了该接口的一个类;
Com com:此时com为一个空接口;
ImpleCom object = new ImpleCom():创建一个实现Com接口的对象object;
com = object:此时com能够操纵object实现的接口的方法;
3.接口回调 VS 多肽
- 接口回调是实现接口的类的实例的引用赋值给接口变量后,该接口变量就可以回调类重写的接口方法。
- 不同的类在实现同一个接口时可能具有不同的实现方式,那么接口变量就在回调接口方法时可能具有多种形态。
4.接口参数
- 如果一个方法的参数为接口类型的数据,那么可以将任何实现该接口的类的实例的引用传递给该参数,接口参数也可以回调类实现的方法。
5.接口回调的步骤
- 所谓的回调,不过就是接口使用匿名内部类而已。
- 我理解的回调,就是:
定义接口;
定义方法;
方法参数为接口,
方法中调用接口;
调用该方法,传入的一个接口实现类; - 其实最常见的是在接口中传入匿名内部类。
6.回调函数
- 在计算机程序设计中,回调函数,或简称回调,是指通过函数参数传递到其它代码的,某一块可执行代码的引用。
- 这一设计允许了底层代码调用在高层定义的子程序。
- 在Java里面使用接口来实现回调。
7.回调实现
- 所谓的回调,就是程序员A写了一段程序(程序a),其中预留有回调函数接口,并封装好了该程序。
程序员B要让a调用自己的程序b中的一个方法,于是他通过a中的接口回调自己b中的方法。
7.1 首先定义一个类Caller,按照上面的定义就是程序员A写的程序a,这个类里面保存一个接口引用。
public class Caller {
//保存一个接口引用
private MyCallInterface callInterface;
public Caller() {
}
public void setCallFunc(MyCallInterface callInterface) {
this.callInterface = callInterface;
}
public void call() {
callInterface.printName();
}
}
7.2 当然需要接口的定义,便于程序员B根据我的定义编写程序实现接口。
public interface MyCallInterface {
public void printName();
}
7.3 第三是定义程序员B写的程序b实现接口。
public class Client implements MyCallInterface {
@Override
public void printName() {
System.out.println("This is the client printName method");
}
}
7.4 测试如下
public class Test {
public static void main(String[] args) {
Caller caller = new Caller();
caller.setCallFunc(new Client());
caller.call();
}
}
7.5 也可以在测试方法中直接使用匿名类,省去第3步。
public class Test {
public static void main(String[] args) {
Caller caller = new Caller();
//caller.setCallFunc(new Client());使用匿名类代替
caller.setCallFunc(new MyCallInterface() {
public void printName() {
System.out.println("This is the client printName method");
}
});
caller.call();
}
}
经验
- 到这里应该明白了吧,这不就是接口作为参数。
- 可以将接口类型的参数作为方法参数,在实际是使用时可以将实现了接口的类传递给方法,后方法或按照重写的原则执行,实际调用的是实现类中的方法代码体,这样便根据传进入的参数的不同而实现不同的功能。
8.典例n多
8.1 例一
interface Extendbroadable ...{
public void inPut();
}
class KeyBroad implements Extendbroadable ...{
public void inPut() ...{
System.out.println(" hi,keybroad has be input into then mainbroad! ");
}
}
class NetCardBroad implements Extendbroadable ...{
public void inPut() ...{
System.out.println(" hi,netCardBroad has be input into then mainbroad! ");
}
}
class CheckBroad ...{
public void getMainMessage(Extendbroadable ext)...{
ext.inPut();
}
}
public class InterfaceTest01 ...{
public static void main(String []args) ...{
KeyBroad kb=new KeyBroad();
NetCardBroad ncb=new NetCardBroad();
CheckBroad cb=new CheckBroad();
cb.getMainMessage(kb);
cb.getMainMessage(ncb);
}
}
8.2 例二 多见的接口上使用匿名内部类
btn_activity.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
i1 = new Intent(MainActivity.this,Main2Activity.class);
startActivity(i1);
}
)};
9.额外收获
- 我之所以会想到这个问题,是因为看到Fragment与Activity使用接口回调通信。
- Fragment中定义一个内部回调接口,让包含该Fragment的Activity实现该回调接口,Fragment就可以通过回调接口传数据了。
9.1 在Fragment中定义一个接口,接口中定义抽象方法,传什么类型的数据参数就设置为什么类型;
/*接口*/
public interface CallBack{
/*定义一个获取信息的方法*/
public void getResult(String result);
}
9.2 在Fragment中接着还有写一个调用接口中的抽象方法,把要传递的数据传过去;
*(msg的获取不要弄错位置了,容易空指针异常)
/*接口回调*/
public void getData(CallBack callBack){
String msg = medit.getText().toString();
callBack.getResult(msg);
}
9.3 在Activity中适当时机使用接口,重写抽象方法获取数据;
final MyFragment f1 = new MyFragment();
getSupportFragmentManager().beginTransaction().add(R.id.mylayout, f1).commit();
button = (Button) findViewById(R.id.btn);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
f1.getData(new MyFragment.CallBack() {
@Override
//使用接口回调获取数据
public void getResult(String result) { /*打印信息*/
Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
}
});
}
});
- 在这里,点击事件中调用Fragment.getData()方法,传入的参数是一个实现了接口的匿名内部类(该内部类重写了getResult()方法),在运行getData()方法时,获取到当前对象中的msg变量,将msg作为参数传入callBack.getResult(msg)方法,在Activity界面中得到了Fragment中的信息,所以实现了类间的数据传递。
- 这也可以说明,传入的接口不同,获得不同的实现。
作者:乌和兔
链接:https://www.jianshu.com/p/f05730ab5d05
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
课堂案例:
什么是接口回调?
1、首先知道什么是接口/标准
就如电脑里面的USB接口,这种是一种通用的外设设备的插口,他不关心那些设备是什么东西(实现方式),
他只关心,是否符合他的接口标准,如usb3.0插口,只要符合就能插上。
2、什么是接口实现者(接口实现类)
还是usb插口,像usb风扇、鼠标、外设键盘等,他们的功用都不一样,只有一点是相同的,
就是他们都使用的是usb这种接口(插口)标准
3、什么是接口的使用者
就像电脑本身,他有usb的插口,而电脑需要使用到某些设备的时候就需要使用的usb接口,所以电脑就是usb接口的使用者
那么接口回调是什么呢?
首先我们先需要有1台电脑,他本身就有着usb的插口(类里面有接口对象存在),当我们要使用外设设备如键盘的时候,我们就要把键盘的usb线给链接上去,中间的桥梁是usb的插口,我们也可以把鼠标连到这个接口上(同一个接口),然后电脑再去使用它(接上usb后通电的动作),在这个时候,电脑并不知道我们给会他接上什么设备,当设备接上去,设备就会自己去使用(风扇自己转、键盘能敲字)。
换到我们的代码说法就是,我们有了usb这个接口标准在了,然后先有了电脑去使用Usb,但是usb本身是什么我们不知道,当我们需要使用了,就给创建usb接口的实现类如风扇,然后直接给到我们的usb使用者就是电脑,电脑在方法中,去调用了我们usb接口的方法。
interface usb{
public void use();
}
class mouse implements usb{
public void use(){
syso(使用鼠标);
}
}
class computer{
Usb usb;
//get/set
public void use(){
usb.use();
}
}
class test{
main(){
computer c = new computer();
c.setUsb(new mouse ());
c.use();
}
}
```