7.从零开始学习Java-接口和面向对象原则

接口

/*1.接口:告诉有什么方法;

2.实现者:implements,实现了接口中的方法;

3.使用者:调用接口,使用接口方法。

*/

//sort排序方法的对象需要实现comparable类。

一、什么是接口

接口相当于特殊的抽象类,定义方式、组成部分与抽象类类似。

微观概念:接口是一种能力和约定。

接口的定义:代表了某种能力。

方法的定义:能力的具体要求。

宏观概念:接口是一种标准。

接口的语法:

接口相当于特殊的抽象类,定义方式、组成部分与抽象类似。

公开静态常量:静态(类),最终(无法修改)的。不必创建对象。

公开抽象方法:更自然的使用多态,不能创建对象。

interface MyInterface{//使用interface关键字定义接口
    //只能定义:公开静态变量、公开抽象方法
    //没有构造方法,不能创建对象,例如不能new父类
    //公开静态常量
    public static final String FIELD = "value";
    //或者简单写,(默认)隐式存在公开静态常量
    String FIELD2 = "Hi";
    //公开抽象方法
    public abstract void method();
    //或者简单写,(默认)隐式存在公开公开抽象方法
    void method2();
}

二、与抽象类的异同

相同:

  • 可编译成字节码文件。
  • 不能创建对象。
  • 可以作为引用类型。
  • 具备Object类中所定义的方法。

不同:

  • 所有属性都是公开静态常量,隐式使用public static final修饰。
  • 所有方法都是公开抽象方法,隐式使用public abstract修饰。
  • 没有构造方法、动态代码块、静态代码块。
//抽象类
abstract class MyClass {
    static int a;//类可以定义,接口不行。jdk1.8之后有静态方法和默认方法。
    //1.(抽象方法)不能new对象(对象不能独立存在,不能使用构造方法)
    public static final String FIELD = "Hello";
    //2.抽象方法(子类必须覆盖)public abstract void m1();
    public abstract void method();
}
//接口
interface MyInterface {
    //1.公开静态常量
    public static final String FIELD = "Hello";
    //或者简单写,(默认)隐式存在公开静态常量
    String FIELD2 = "Hi";
    //2.公开抽象方法
    public abstract void method();
    //或者简单写,(默认)隐式存在公开公开抽象方法
    void method2();
}
//测试类
public class TestBasicInterface {
    public static void main(String[] args){

    }
}

三、接口的应用

接口的规范:

//实现抽象类,修饰符必须为public

  • 任何类在实现接口时,必须实现接口中的所有抽象方法,否则此类为抽象类。
  • 实现接口中的抽象方法时,访问修饰符必须是public。

单继承与多继承:

//接口实现超脱了父类约定的抽象方法

  • Java为单继承,当父类的方法种类无法满足子类需求时,可实现接口扩充子类能力。
  • 接口支持多实现,可为类扩充多种能力
类与类:

单继承

extends 父类名称

类与接口:(实现关系)

多实现

implements 接口名称1,接口名称2,接口名称n

接口与接口:(继承关系)

多继承

extend 父接口1,父接口2,父接口n

//父类
abstract class Animal1 {
    String breed;
    int age;
    String sex;
    //抽象方法(规定子类必须存在的行为、规范了该行为的具体要求)
    public abstract void eat();
    public abstract void sleep();
}
//接口
//Runnable接口
//接口是一种能力
public interface Runnable {
    //接口(中的方法)是一种约定
    public abstract void run();
}
//Swimmable接口
public interface Swimmable {
    public abstract void swim();
}
//Climbable接口
public interface Climbable {
    public abstract void climb();
}
//子类
//猫
public class Cat1 extends Animal1 implements Runnable,Climbable{//多实现
    String furColor;
    public void eat(){
    }
    public void sleep(){
    }
    //独有方法
    public void run(){
    }
    public void climb(){
    }
}
//狗
public class Dog1 extends Animal1 implements Runnable{//实现
    String furColor;
    public void eat(){
    }
    public void sleep(){
    }
    //独有方法
    public void run(){
    }
}
//鱼
public class Fash1 extends Animal1 implements Swimmable{
    public void eat(){
    }
    public void sleep(){
    }
    //独有方法
    public void swim(){
    }
}

接口引用:

同父类一样,接口也可声明为引用,并指向实现类对象。

注意://可进行拆箱即向下转型来调用未声明的方法(独有方法)。

  • 仅可调用接口中所声明的方法,不可调用实用类中独有的方法。
  • 可强转实现类本身类型,进行独有方法调用。(拆箱)

接口的多态:

接口引用指向实现类对象

多种不同类型的引用指向同一个对象时,表示看待对象的视角不同。

不同引用所能看到的对象范围不同,只能调用自身类型中所声明的部分。

总之,不同引用类型,仅可调用自身类型中所声明的方法。

类的多态:父类引用指向子类对象。//狗是一种动物(把狗当成动物来看)

接口的多态:接口引用指向实现类对象。//狗是一种会跑的东西(把狗当成一种会跑的东西来看待)

//同上一例子
//测试类
//父类比接口范围更泛
public class TestAble {
    public static void main(String[] args){//使用者
        //狗是一种动物(把狗当成动物来看)
        Animal1 animal1 = new Dog1();//父类引用指向子类对象(多态)
        
         //向下转型
        ((Dog1) animal1).run();
        
        //狗是一种会跑的动物(把狗当成一种会跑的东西来看待)
        Runnable r = new Dog1();//接口引用指向实现类对象(更自然的多态)
        r.run();
        Runnable r2 = new Bus();
        r2.run();
        //r中存储了一个会跑的东西,我需要调用接口以外的内容
        Dog1 mydog = (Dog1) r;
        //拆箱(向下转型)
        mydog.eat();
        //((Dog1) r).eat();
        mydog.sleep();
        
       //当然这样也可以,但是不提倡,不符合多态、继承的思想
        //Dog1 dog1 = new Dog1();
        //dog1.eat();
    }
    }
}
//Runnable接口
//接口是一种能力
public interface Runnable {
    //接口(中的方法)是一种约定
    public abstract void run();
}
//Bus类
public class Bus implements Runnable {//实现者
    @Override
    public void run() {
        System.out.println("以每小时1m狂飙");
    }
}

四、常量、标记接口

常量接口:

将多个常用于表示状态或固定值的变量,以静态常量的形式定义在接口中统一管理, 提高代码可读性。

public interface Light {
    public static final int RED = 1;
    int YELLOW = 2;
    int GREEN = 3;
}
public class TestInterfaceExtends {
    public static void main(String[] args){
        int currentLight = Light.GREEN;//直接类名.调用
        int currentLight2 = Light.RED;
        int currentLight3 = Light.YELLOW;
    }
}
//利用枚举
//枚举,规范了取值的类型
public enum Light1 {
    GREEN,YELLOW,RED
}
public class TestInterfaceExtends {
    public static void main(String[] args){
        Light1 currentLight4 = Light1.GREEN;//枚举
    }
}

标记接口:

接口没有任何成员,仅仅是一个标记。Serializable、Cloneable


五、回调原理

在这里插入图片描述

宏观概念:接口是一种标准。

接口回调:先有接口,先有接口的使用者,后有接口的实现者。

//implements为实现者。

//创建对象,使用接口为使用者。

public class TestUSB{
	public static void main(String[] args){		
		//程序猿		
		Computer c1 = new Computer();				
		c1.on(new Fan() , new Lamp() , new UDisk() );//使用工具		
	}
}
class Computer{//工具
	
	USB u1;
	USB u2;
	USB u3;
	
	public void on(USB u1 , USB u2 , USB u3){
		this.u1 = u1;
		this.u2 = u2;
		this.u3 = u3;
		
		System.out.println("开机,进入操作页面...");
		
		//接口的使用者
		u1.service();
		u2.service();
		u3.service();
	}
	
}

interface USB{
	//服务
	public void service();
}

class Fan implements USB{
	
	public void service(){
		System.out.println("旋转...");
	}
	
}

class Lamp implements USB{
	public void service(){
		System.out.println("照明...");
	}
}

class UDisk implements USB{
	public void service(){
		System.out.println("读写数据...");
	}
}

六、JDK1.8接口变化

1.提供了静态方法和默认方法,分别使用 static 和 default 关键字修饰,这两种方法可以有方法体 (下面是需要注意的地方)。
[1]:default 方法属于实例,static 方法属于接口或类。要注意的是:default 方法可以被继承,static 方法不会。
[2]:如果一个类实现了多个接口,并且这些接口之间没有相互继承关系,同时存在相同的 default 方法时会报错,不过你可以在实现类中重写 default 方法并通过 <接口>.super.<方法名>(); 形式指定调用哪个父接口中的 default 方法。

2.如果一个接口只有一个抽象方法,那么这个接口会默认自动变成函数式接口。

3.如果使用了@FunctionalInterface 注解对接口进行修饰,说明这个接口是一个函数式接口,在该接口只能有一个抽象方法 (不限制静态方法和默认方法)。一个函数式接口可以通过 Lambda 表达式来创建该接口的对象。

//[1]
public interface TestInterface {
    static void testStaticMethod(){
        System.out.println("static method run");
    }
    default void testDefaultMethod(){
        System.out.println("default method run");
    }
}

class Test implements TestInterface {
    public static void main(String[] args) {

        Test test = new Test();
        test.testDefaultMethod();//default 方法可以被继承,static 方法不会。
        //test.testStaticMethod();  Static method may be invoked on containing interface class only
        TestInterface.testStaticMethod();   //对于接口中的静态方法可以使用接口名直接调用
    }
}
输出
default method run
static method run
//[2]
public interface TestInterface {
    default void testDefaultMethod(){
        System.out.println("TestInterface default method run");
    }
}

interface TestInterface1{
    default void testDefaultMethod(){
        System.out.println("TestInterface1 default method run");
    }
}

class Test implements TestInterface,TestInterface1 {//在实现类中重写 default 方法并通过 <接口>.super.<方法名>(); 形式指定调用哪个父接口中的 default 方法
    public void testDefaultMethod(){
        TestInterface1.super.testDefaultMethod();
    }

    public static void main(String[] args) {

        Test test = new Test();
        test.testDefaultMethod();
    }
}
输出
TestInterface1 default method run
//2、3
@FunctionalInterface
public interface TestFunctionalInterface {//函数式接口,在该接口只能有一个抽象方法
    static void staticMethod(){}    //在函数式接口中不限制定义静态方法与默认方法
    default void defaultMethod(){}

    void functionalInterfaceMethod();
    // void functionalInterfaceMethod2(); 不允许
}

接口的好处:

  • 程序的耦合度降低。
  • 更自然的使用多态。
  • 设计与实现完全分离。
  • 更容易搭建程序框架。
  • 更容易更换具体实现。

七、总结:

什么是接口:

  • 微观:接口是一种能力和约定。
  • 宏观:接口是一种标准。

接口与类的异同:

没有构造方法,仅可定义公开静态常量与公开抽象方法。

接口的应用:

Java为单继承,当父类的方法种类无法满足子类需求时,可实现接口扩充子类能力。

接口的规范:

任何类在实现接口时,必须实现接口中所有的抽象方法,否则此类为抽象类。

实现接口中的抽象方法时,访问修饰符必须是public。

什么是常量接口:

将多个常用于表示状态或固定值的变量,以静态常量的形式定义在接口中统一管理。

什么是接口回调:

先有接口的使用者,后有接口的实现者。

八、面向对象的设计原则

口诀:开口里合最单依

总则:

开闭原则

单一职责原则

里氏替换原则

依赖倒置原则

接口隔离原则

迪米特法则(最小知道原则)

合成复用原则

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值