接口详解.

一、终极结论

接口:
  1、接口也是一种“引用数据类型”
  2、接口是完全抽象的(抽象类是半抽象)
  3、接口怎么定义,语法是什么?
  [修饰符列表] interface 接口名{}
  4、接口中只有常量、抽象方法
  5、接口当中所有的元素都是public修饰的
  6、接口中抽象方法的public abstract可以省略
  7、接口中常量public static final可以省略
  9、接口中方法不能有方法体
 10、接口支持多继承
 11、一个"非抽象"的类,实现(可以理解为继承)接口时,必须将接口中所有的"抽象"方法加以实现(重写)
 12、一个类可以实现多个接口
 13、extends和implements可以共存,extends在前,implements在后
 14、使用接口写代码的时候,可以使用多态(父类型引用指向子类型对象)
 15、接口的使用离不开多态机制(因为接口是完全抽象类无法创建对象
 多态刚好父类型引用指向子类型对象)

public class homework01 {
    public static void main(String[] args) {
        // 访问接口常量
        System.out.println(A.PI); // 3.15159
        // 常量能重新赋值吗? 不能:因为常量被final修饰了
        // A.PI =3.1415926; // 报错:无法为最终变量PI分配值
    }
}
// 定义接口
interface A{
    // 常量
    // public static final double PI =3.14159;
    // 接口当中既然都是常量,那么public static final 能不能省略? 答案:可以
    double PI =3.14159; // 写一个常量编译器发现是接口也会把变量当成常量 public static final double PI

    // 接口中随便写一个变量就是常量【常量:值不能改变的变量】

    // 抽象方法
    // public abstract int sum(int a,int b);
    // 接口当中既然都是抽象方法,那么在编写代码的时候,可不可以把public abstract省略? 答案: 可以
    int sum(int a,int b);

}

// 接口支持继承
interface B extends A{

}

// 接口支持多继承
interface C extends A,B{}

 二、接口的基础语法

public class homework01 {
    public static void main(String[] args) {
        // 能使用多态吗? 可以
        // 父类型的引用指向子类型的对象[子类为“非抽象”类 所以可以创建对象]
        MyMath mm =new MyMathImPm();
        // 调用接口里面的方法(面向接口编程)

        // mm.sum(参数);
        // 编译时: 先在父类MyMath当中绑定sum方法
        // 运行时: 在子类MyMathImPm当中找到sum方法进行运行
        System.out.println(mm.sum(10,30)); // 40
        System.out.println(mm.sub(90,40)); // 50

    }
}

// 接口(完全抽象的类 叫做接口)
interface MyMath{
    // 常量 public static final double PI =3.1415926;
    double PI =3.1415926;

    // 抽象方法 public abstract int sum();
    int sum(int a,int b);
    int sub(int a,int b);
}

// 编写一个MyMathImPm类(这个类是一个"非抽象"类)
/*
class MyMathImPm implements MyMath{
    // 注意: 方法体当中不写任何代码的话会报错:因为MyMathImPm这个类是“非抽象”类,而实现(继承)的类为抽象类 继承的方法为抽象方法
    // 而抽象方法必须在抽象类当中 所以报错:MyMathImPm不是抽象的, 并且未覆盖MyMath中的抽象方法sum(int,int)
}
*/
// 修正
class MyMathImPm implements MyMath{
    //  重写/覆盖/实现 接口中的方法(通常叫做实现)
     public int sum(int a,int b){
        // 因为为int型方法所以要有返回值
        return a+b;
    }

    public int sub(int a,int b){
        return a-b;
    }

    /*
    思考: 能不能把方法中的public去掉?
    答案:不能 报错:正在尝试分配更低的访问权限; 以前为public[接口当中所有抽象方法都是public修饰的,继承下来的话不能将访问权限降低]
    int sum(int a,int b){
         return a+b;
    }
     */
}

三、一个类可以实现多个接口

一个类可以实现(继承)多个接口

这种机制弥补了java中的哪个缺陷?
   java中类和类只支持单继承,实际上单继承是为了简单而出现的,现实世界中存在多继承,java中的接口弥补了单继承带来的缺陷

public class homework01 {
     public static void main(String[] args) {
         // 多态该怎么用呢?
         // 都是父类型引用指向子类型对象
         A a =new D(); // 【向上转型】
         B b =new D();
         C c =new D();

         // 思考: a.m2(); 怎么实现【m2在B抽象类当中 而a为A抽象类 A与B抽象类没有继承关系】
         // 强制转换【向下转型】
         B b2 =(B)a;
         b2.m2();   // 输出结果:m2.....



     }
}
/*
 // 接口和接口支持多继承
 interface X{

 }
 interface Y{

 }
 interface Z extends X,Y{

 }
 */

 // 一个“非抽象”类可以实现多个接口
 interface A{
    void m1();
 }
 interface B{
     void m2();
 }
 interface C{
    void m3();
 }

class D implements A,B,C{
     public void m1(){
         System.out.println("m1.....");
     }
    public void m2(){
        System.out.println("m2.....");
    }
    public void m3(){
        System.out.println("m3.....");
    }

}

四、extends 和 implements关键字同时存在时 

继承和实现都存在的话,代码应该怎么写?
     extends 关键字在前
     implements 关键字在后

public class homework01 {
     public static void main(String[] args) {
          // 创建对象(表面看Animal类没起作用:先不用管)
           Flyable f1 =new Cat();  // 多态
           f1.fly();

           Flyable f2 =new Pig();
           f2.fly();

           Flyable f3 =new Fish();
           f3.fly();
                }
}



// 动物类: 父类
class Animal{
     }


// 可飞翔的接口(是一对翅膀)
interface Flyable{
     // 飞翔的抽象方法
     void fly();
}

// 动物类:子类
// Flyable是一个接口,是一对翅膀的接口,通过接口插到猫身上,让猫可以飞翔
class Cat extends Animal implements Flyable{
     // 当“非抽象”类Cat实现[实现:可以理解为继承]“完全抽象”类Flyable时候 需要重写方法
     public void fly(){
          System.out.println("飞猫起飞,翱翔太空的一只猫,很神奇,我想做一只猫~");
     }
}

// 狗类: 如果你不想让它起飞,可以不实现Flyable接口
// 没有实现这个接口表示你没有翅膀,没有给你翅膀,你肯定不能飞
class Dog extends Animal{

}

// 想飞就给翅膀这个接口
class Pig extends Animal implements Flyable{
     public void fly(){
          System.out.println("我是一只会飞的猪~");
     }
}

// 鱼 (没写继承,默认实际上是存在继承的,默认继承object类)
// class Fish extends object implements Flyable{}
class Fish implements Flyable{     // 没写extends继承时默认继承object类
     public void fly(){
          System.out.println("我是六眼飞鱼(流言蜚语)~");
     }
}

 运行结果:

 五、接口在开发中的作用

面向抽象编程这句话以后可以改为:面向接口编程

     分析:
     中午去饭馆吃饭,这个过程有接口吗?
     接口是抽象的
     菜单是一个接口(菜单上有一个抽象的图片:西红柿炒鸡蛋)
     谁面向这个接口?(顾客面向菜单点菜,调用接口)
     谁负责实现这个接口呢?(后厨的厨师负责把西红柿炒鸡蛋做好,是接口的实现者)
     这个接口有什么用呢?
      这个饭馆的“菜单”,让“顾客”和“厨师”解耦合了
      顾客不用找后厨,后厨不用找顾客,他们之间完全依靠抽象的“菜单”沟通

菜单 接口 抽象的

// 菜单 接口 抽象的
public interface FoodMenu {

    // 西红柿炒鸡蛋 抽象方法
    void xiHongShiChaoJiDan();
    // 鱼香肉丝
    void yuRouSi();
}

厨师

// 西餐厨师
// 实现菜单上的菜
// 厨师是接口的实现者
public class AmericCooker implements FoodMenu{
    // 西红柿炒鸡蛋
    public void xiHongShiChaoJiDan(){
        System.out.println("西餐厨师做的西红柿炒鸡蛋");
    }
    // 鱼香肉丝
    public void yuRouSi(){
        System.out.println("西餐厨师做的鱼香肉丝");
}
}
// 中餐厨师
// 实现菜单上的菜
// 厨师是接口的实现者
public class ChinaCooker implements FoodMenu {
    // 西红柿炒鸡蛋
    public void xiHongShiChaoJiDan(){
        System.out.println("中餐厨师做的西红柿炒鸡蛋");
    }
    // 鱼香肉丝
    public void yuRouSi(){
        System.out.println("中餐厨师做的鱼香肉丝");
    }
}

顾客

// 顾客
public class Customer {
    // 顾客手里有一个菜单
    // Customer has a FoodMenu(这句话的意思:顾客有一个菜单)
    // 记住: 凡是能够使用 has a 来描述的,统一以属性(变量)的方式存在
    // 实例变量 属性
    // 面向抽象编程,面向接口编程,降低程序的耦合度,提高程序的扩展力
    private FoodMenu foodMenu; // 要养成封装的好习惯 [相当于把FoodMenu类交给foodMenu引用]

    /*
    如果以下这样写就表示写死了 表明顾客只能吃西餐或者中餐,【耦合度高了,扩展力差】
    【FoodMenu是一个更抽象的父类型 ChinaCooker,AmericCooker都已经实现了FoodMenu】
    中餐厨师
    ChinaCooker cc;

    西餐厨师
    AmericCooker ac;
     */

    // 提供一个点菜的方法
    public void order(){
        // 先拿到菜单才能点菜
        FoodMenu fm =this.getFoodMenu(); // FoodMenu相当于类型(String int double...)
        fm.xiHongShiChaoJiDan();
        // 也可以不用get方法,因为在本类中私有的属性是可以直接访问[私有属性当中刚好把菜单类赋给了引用foodMenu]
        // foodMenu.yuRouSi();
    }

    // 构造方法
    public Customer() {
    }

    public Customer(FoodMenu foodMenu) {
        this.foodMenu = foodMenu;
    }

    public FoodMenu getFoodMenu() {
        return foodMenu;
    }

    public void setFoodMenu(FoodMenu foodMenu) {
        this.foodMenu = foodMenu;
    }
}

代码测试

public class ImplementsTest {
    public static void main(String[] args) {
         // 创建厨师对象
       FoodMenu cooker1 =new ChinaCooker(); // 因为ChinaCooker实现了FoodMenu,相当于cooker1引用还是指向了菜单FoodMenu类
        // 创建顾客对象
        Customer customer =new Customer(cooker1); // 传的相当于是菜单
        // 顾客点菜
        customer.order();

    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值