zoukankan      html  css  js  c++  java
  • Java学习笔记 -接口

    接口

    1.接口是引用数据类型
    2.接口是完全抽象的(抽象类是半抽象)或者也可以说接口是特殊的抽象类
    3.接口的语法: [修饰符列表] interface 接口名{}
    4.接口与接口之间, 接口与类之间都支持多继承
    5.接口只包含常量和抽象方法,所以没有构造方法
    6.接口中所有的元素都是public修饰的
    7.接口的抽象方法定义时: public abstract 修饰符可以省略

    • 接口中的常量定义时:public static final 修饰符可以省略
    • 在编译器编译的时候会自动加上

    接口的基本使用

    1.类和类之间叫做继承,类和接口之间叫做实现(可以将“实现”理解为“继承”)

    • 继承使用extends关键字完成
    • 实现使用implements关键字完成
      2.当一个非抽象的类实现接口的话,必须将接口中所有的抽象方法全部实现(覆盖)
    interface MyMaths{
            //这里要知道常量和方法都是省略了关键字的
    	double PI = 3.14;
    	int sum(int a ,int b);
    	int sub(int a, int b);
    }
    
    class MyMathsImpl implements MyMaths{
    	//方法覆盖(这里通常叫做实现)
    	public int sum(int a, int b){
    		return a + b;
    	}
    	public int sub(int a, int b){
    		return a - b;
    	}
    }
    public class InterfaceTest{
    	public static void main(String[] args){
    		//多态
    		MyMaths m = new MyMathsImpl();
    		int a = m.sum(1, 2); 
    		System.out.println(a);
    	}
    }
    

    一个类是否可以实现(继承)多个接口吗?

    可以,这种机制弥补了Java类和类只支持单继承。

    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...");
    	}
    }
    
    public class InterfaceTest{
    	public static void main(String[] args){
    		//多态
    		//父类型引用指向子类型对象
    		A a = new D();
    		B b = new D();
    		C c = new D();
    		
    		//接口之间没有继承关系,是否可以强制类型转换(接口转型)
    		//属于骚操作,明明没有继承关系,还能转型,现阶段还是不要去记它,用处不大
    		B b1 = (B)a;
    		b1.m2();
    		
    		//如果想让a调用m2方法,还是直接向下转换成D即可
    		D d = (D)a;
    		d.m2();
    	}
    }
    

    无论向上转型还是向下转型,两种类型之间必须要有继承关系,没有继承关系编译器会报错,但是这句话不适用在接口方面。
    想要父类型引用调用子类型特有的方法,还是使用将父类型引用向下转型为子类型对象这种语法最好。

    没有继承关系的接口之间转型

    interface K{
    }
    interface M{
    }
    class E implements M{
    	
    }
    public class InterfaceTest{
    	public static void main(String[] args){
    		M m = new E();
    		K k = (K)m;
    	}
    }
    


    接口和接口之间进行强制类型转换的时候,没有继承关系,也可以强制类型转换,编译器不会报错
    但是要注意,在运行时可能会出现ClassCastException异常

    解释为什么第一个程序没有出现异常?
    • 首先,语法上即使没有继承关系,类或者接口类型(不能new接口对象)强制类型转化成其他接口编译是可以通过的
    • 但是运行期间,如果类或者接口类型所代表的实际对象没有实现其他接口,那么就会报ClassCastException异常。
    • 因此,例如第二个例子,好的写法是if(m instanceof K) K k = (K) m;

    继承和实现都存在的话,代码应该怎么写?

    extends 在前 implements 在后

    class Animal{
    	
    }
    //可飞翔的接口,接口通常提取的是行为动作
    interface Flyable{
    	void fly();
    }
    
    class Cat extends Animal implements Flyable{
    	public void fly(){
    		System.out.println("飞翔的小猫");
    	}
    }
    
    
    //如果不想让它飞,可以不实现Flyable的接口
    class Snake extends Animal{
    	
    }
    
    //想飞就插入Flyable接口
    class Pig extends Animal implements Flyable{
    		public void fly(){
    		System.out.println("飞翔的小猪");
    	}
    }
    public class Test{
    	public static void main(String[] args){
    		//多态
    		Flyable f = new Cat();
    		f.fly();
    		
    		Flyable f1 = new Pig();
    		f1.fly();
    	}
    }
    


    这个例子体现了接口“可插拔”的特点,这降低了程序之间的关联性,也就是解耦合。

    接口在开发中的作用

    • 接口是完全抽象的,
    • 面向抽象编程这样修改为:面向接口编程
    • 有了接口就有了可插拔。可插拔表示扩展力很强,不是焊死的
    • 主板和内存直接有插槽,这个插槽有接口,内存条坏了可以换下来,这个叫做高扩展性(低耦合度)
    总结一句话:

    面向接口编程,可以降低程序的耦合度,提供程序的扩展力,符合OCP原则
    接口的使用离不开多态机制

    //接口 -菜单
    public interface FoodMeau {
    
        public void shihongshi();
        public void rousi();
    
    }
    
    
    //接口的实现
    //西餐师傅
    //厨师是接口的实现者
    public class AmericanCooker implements FoodMeau{
        public void shihongshi(){
            System.out.println("西餐师傅做的西红柿炒蛋");
        }
        public void rousi(){
            System.out.println("西餐师傅做的鱼香肉丝");
        }
    }
    
    //中餐厨师
    public class ChineseCooker implements FoodMeau{
        public void shihongshi(){
            System.out.println("中餐师傅做的西红柿炒蛋,超好吃的");
        }
        public void rousi(){
            System.out.println("中餐师傅做的鱼香肉丝,超好吃的");
        }
    }
    
    //接口的调用者 -顾客
    public class Customer {
        //顾客手里有一个菜单
        //Customer has a FoodMenu
        //记住:以后凡是能够使用 has a 来描述的,统一以属性的方式存在
        //回顾:凡是能用 is a来描述的,都可以设置为继承
        private FoodMeau foodMeau;
    
        //Constructor
        public Customer() {
        }
        public Customer(FoodMeau foodMeau) {
            this.foodMeau = foodMeau;
        }
    
        //setting and getter
        public FoodMeau getFoodMeau() {
            return foodMeau;
        }
    
        public void setFoodMeau(FoodMeau foodMeau) {
            this.foodMeau = foodMeau;
        }
    
        //提供点菜的方法
        public void order(){
            FoodMeau f = getFoodMeau();
            f.shihongshi();
            f.rousi();
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            //建立厨师对象
            FoodMeau cooker1 = new ChineseCooker();
            FoodMeau cooker2 = new AmericanCooker();
            //建立顾客对象
            Customer c = new Customer(cooker1);
    
            //顾客点菜
            c.order();
            //如果想要点西餐
            c.setFoodMeau(cooker2);
            c.order();
        }
    }
    

    接口可以解耦合:

    任何一个接口都有调用者和实现者,接口可以将调用者和实现者解耦合
    调用者面向接口编写调用,实现者面向接口编写实现.
    大型项目的开发,一般都是将项目分离成一个模块一个模块的,
    模块和模块之间采用接口衔接,降低耦合度.

  • 相关阅读:
    favourite programming quotes
    a fast algorithm to compute the area of a polygon
    customize your own memory allocator (2)
    一道概率算法
    study on source code of Tcmalloc
    智力题2
    how does malloc/free work?
    Windows PowerShell系列课程(视频课程讲师:李大川)
    跟我一起学Visual Studio 2008系列课程(视频课程讲师:徐长龙)
    C# 3.0 锐利体验系列课程(视频课程讲师:李建忠)
  • 原文地址:https://www.cnblogs.com/zy200128/p/12726663.html
Copyright © 2011-2022 走看看