JAVA interface 将接口作为参数传递的方法

2019-06-24  本文已影响0人  black_history

1.什么是接口?

接口是Java编程语言中的一种抽象类型,是抽象方法的集合,通常以interface来声明,所以接口不是类,尽管写法相似。
一个类通过实现接口的方式来继承接口的方法。
除非实现接口的类是抽象,否则该类要定义接口中所有方法。
接口无法被实例化,但是可以被实现。
等等......
2.接口与类的区别(不探讨具象类与抽象类的区别,只探讨类与接口的区别)
接口不是类,抽象类与接口也不一样。
虽然抽象类中的抽象方法与接口中的抽象方法是一个概念,但是抽象类是类,它可以包含具体的方法,而接口只能有抽象方法。
接口继承接口,继承到接口所有方法;类实现接口,如果是非抽象类,必须实现接口中的所有方法。
3.为什么抽象类不必(是不必,不是不能)定义接口中所有方法?
抽象类和接口的定义虽然不同,但是其目的是一致的,通过继承抽象类/实现接口来继承抽象类/接口中的抽象方法,并定义其具体实现。
当抽象类实现接口时,虽然继承了接口所有方法,但是根据实际情况,接口中有些(甚至所有)抽象方法是不必定义的,那么便按需定义。
当另一个类继承该抽象类时,再去定义这些方法。

这里有详细的解释,并附有案例:
深入理解Java的接口和抽象类

将接口作为值传递?

public class A {
  private TestInterface test;
  public A(TestInterface test) {
    this.test = test; 
    doSth();
  }
   public void doSth() {
    test. systemStr("this is a message!");
  }
}

public Interface TestInterface(){
  void systemStr(String str);
}

public class B implement TestInterface{
  public static void main(String[] args) {
    new A(new B());
   }
    
   @Override
    public void systemStr(String str) {
      System.out(str);
    }
}
且看这两个类,一个接口,它们什么关系?

class B 作为程序入口类,实现了interface TestInterface,并定义了接口中systemStr(String str)

主方法main()中实例化class A,并将自身class B的实例化对象传入。

class A中,定义了一个接口TestInterface类型的成员变量test,一个具体的方法doSth()
其构造方法接受主方法中传来的数据并初始化成员变量test
doSth方法执行方法systemStr()

class A的构造方法明明规定接受类型为TestInterface,为什么向class A的对象中传入的是class B的实例?

这涉及到java自动转型,TestInterface test由编译器自动(向下)转型为class B。实际执行的方法是由class B继承自TestInterface并定义的systemStr(String str)方法。
虽然接受的类型为TestInterface,但是接口不能被实例化,所以我们要定义一个类来实现接口,并将这个类传递过去。
我们大可以规定class A的构造方法接受类型为class B


以下内容为类型转换的解释

什么是向上/向下转型?

首先是什么时候能转型?

二者必须存在继承关系后才能相互转型

什么是向上/向下转型?

向上转型:继承者类型对象(子)被继承者类型(父) 转型(自动转型)

子类 转型为 父类
再比如上面程序中的 接口实现类接口 转型

向下转型:被继承者类型对象(父)继承者类型(子) 转型(强制转型)

比如 父类 转型为 子类
注意:接口不能实例化,没有对象,自然也就不能转型为接口实现类

什么是自动/强制转型?
public Interface Interface1() {
   public void i11(){
    //dosth
  }
  
  public void i12(){
    //dosth
  }
}

public class Parent() implement Interface1 {
  public void p1(){
    //dosth
  }
  
  public void p2(){
    //dosth
  }

  public void i11(){
    //dosth
  }
  
  public void i12(){
    //dosth
  }
}

public Interface Interface2() {
   public void i21(){
    //dosth
  }
  
  public void i22(){
    //dosth
  }
}
public class Child1() extends Parent implement Interface2 {
   public void c11(){
    //dosth
  }
  
  public void c12(){
    //dosth
  }
  
  public void i21(){
    //dosth
  }
  
  public void i22(){
    //dosth
  }
}

public class Child2() extends Parent{
  public void c21(){
    //dosth
  }
  
  public void c22(){
    //dosth
  }

}

如上程序

class Child1继承class Parent,并实现Interface Interface2;
而``class Parent又实现了Interface Interface1`

Parent parent = new Child1()子类转型为父类,即向上转型
new Child1() 转型后的 父类对象parent只能访问与子类Child1共有的方法。
如:父类的全部方法【父类自身的p1()、p2()和继承自接口的i11()、i12()】,子类的方法则不是共有的,不能访问。如果编写parent.c11(); 或者 parent.i21() 则不能通过编译。
你的编辑器可能会提示你这样写(Child1)parent.c11();,这就是强制转型(向下转型)

Child1 child1= (Child1)new Parent()父类转型为子类,即向下转型
new Parent() 转型后的 子类对象 child1能访问子类Child1的全部方法(包括自身方法,继承自父类与接口的方法)。

然而,向上转型是安全的,总是能成功的;向下转型只不安全的,可能会产生ClassCastExcption
比如
以下向下转型是能成功的:

Child1 child1= (Child1)new Parent();
Child2 child1= (Child2)new Parent();

随即,将child1,child2向上转型

Parent parent1 = child1;
Parent parent2 = child2;

再将parent1,parent2按以下方式向下转型是不能成功的

child1 = (Chid1)parent2;
child2 = (Child2)parent1;
//或者
Child1 child11 = (Chid1)parent2;
Child1 child21 = (Chid2)parent1;

因为这相当于将Child2类型强转为Child1类型,将Child1类型强转为Child2类型,它们之间没有继承关系,这是不可行的

当然,以下是可行的

child1 = (Chid1)parent1;
child2 = (Child2)parent2;
//或者
Child1 child11 = (Chid1)parent1;
Child1 child21 = (Chid2)parent2;

这相当于将Child1类型与Child2类型转换回去,自然是能成功的。

补充知识:接口不能实例化,为什么可以写成形如

view.setOncickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {});

的格式?

这不是将OnCLickListener接口实例化,而是匿名内部类的形式。
相当于创建了一个implement了OnCLickListener的类实例,并将其传递。

什么是内部类?什么是匿名内部类?

内部类:是嵌套在类中的类,根据修饰符的不同,还可分为静态内部类、局部内部类等,定义在方法中的内部类,即使为static所修饰,也是局部内部类。
匿名内部类:是一种没有类名的内部类,不使用class、extends、implements,没有构造函数,它必须继承其他类或实现其他接口。但是其本质上依然创建了一个继承了其他类或实现了其他接口类实例。

所以,除了以上new 接口()的内部类形式,还有形如
listView.setAdapter(new BaseAdaptetr(){......});
的new 类() 的内部类形式。

大可在{}中定义新的成员变量、方法甚至新的内部类,只是这些只能在该内部类中访问罢了。

上一篇下一篇

猜你喜欢

热点阅读