Thinking-in-Java接口

17次阅读

共计 3609 个字符,预计需要花费 10 分钟才能阅读完成。

9. 接口

9.1 抽象类和抽象方法

  • 抽象类:包含抽象方法的类,自身无法实例化 <!– 属于接口和普通类的中间形态 –>
  • 抽象方法:仅有声明,没有方法体
  • 关系:抽象方法是抽象类的充分不必要条件,因此抽象类中允许方法实现和抽象方法同时存在
  • 语法

    // 抽象类
    abstract class ClassName{}
    
    // 抽象方法
    abstract void f()
  • 注意点

    • 抽象类中接入接口,则继承抽象类的导出类同样需要实现接口

9.2 接口

  • 接口:完全抽象的类
  • 规则

    • 使用 interface 关键字来替代 class
    • 访问修饰符只允许 public 或者默认的包访问权限
    • 只允许方法名、参数列表、返回类型
    • 方法类型默认固定是 public
    • 接口可以指向实现该接口的对象
  • 用途

    • 建立类与类之间的联系

<!– 接口类型可以使用包权限,但是方法默认为 public–>

9.2.1 接口和抽象类的使用原因——重点

抽象类是抽象若干个类的共同点并用来继承,接口是在导出类中增加导出类需要的特殊方法

1. 问答

  1. 使用接口和抽象类的原因

    依赖倒置原则(Dependecy-Inversion Principle):依赖于抽象。具体而言就是高层模块不依赖于底层模块,二者都同依赖于抽象;抽象不依赖于具体,具体依赖于抽象。

    • 实现多态,能够向上转型 <!– 如果 Farmer 需要喂养动物,则只需要传递信息给 Animal 接口即可,具体喂养的类由多态实现 –>
    • 防止客户端程序员创建该类的对象
  2. 使用接口或抽象类的原因

    • 接口

      • 降低程序模块的耦合 <!– 继承增加模块耦合 –>
      • 需要实现的方法不是基类必要属性 <!– 比如猴子 Smell 方法不是哺乳动物的必要属性,而猴子已经继承了哺乳动物抽象类,因此通过接口实现 –>
      • 作为单继承的补充
    • 抽象类

      • 复用 <!– 比如猴子和大象都是哺乳动物,有 eat(),drink() 方法,所以可以抽象出来 –>
  • 接口和抽象类的异同

9.3 完全解耦

1. 策略设计模式

  • 定义:一个能够根据传递的参数对象的不同而具有不同行为的方法。
  • 策略:传入的参数对象

2. 适配器设计模式

  • 定义:通过适配器类将接受接口,并返回需要的接口
  • 分类:类的适配器、对象的适配器

3. 类的适配器

  • 目的:将接口从具体实现中解耦,使得接口可以应用于多种不同的具体表现 <!– 比如客户需要定制功能,继承现有功能,然后再通过接口补充功能,来实现客户需要的功能 –>
  • 原理:如果有 220V 和 110V 电源两个(被适配对象),手机需要充电(需要实现的功能),这时候需要充电器(适配器),手机的充电方法传入参数为接口对象,原因是实现该接口的类都能作为参数传入(多态的运用)

  • 实现

    <!– 被适配对象 –>

    public class Adaptee220V {int output220V(){return 220;}}
    
    public class Adaptee110V {int output110V(){return 110;}}

    <!– 适配器 –>

    public class Adapter220V extends Adaptee220V implements Target {@Override public int output5V() {int v = super.output220V();
            // 将电压进行转换的具体实现
            int dst = v / 44;
            return dst;
        }
    }
    
    public class Adapter110V extends Adaptee110V implements Target {@Override public int output5V() {int v = super.output110V();
            int dst = v / 22;
            return dst;
        }
    }

    <!– 接口 –>

    public interface Target {int output5V();
    }

    <!– 使用类 –>

    public class Phone {
        // 充电方法,充电需要用到供电方法
        void charging(Target target){int v = target.output5V();
            System.out.println("使用成功,方法为"+target.getClass().getSimpleName()+", 电压为:"+v);
        }
    }

    <!– 测试类 –>

    public class TestAdapter {public static void main(String[] args) {new Phone().charging(new Adapter220V());
            new Phone().charging(new Adapter110V());
        }
    }

9.4 Java 中的多重继承

  • 多重继承:组合多个接口,因为 Java 是单继承
  • 注意点:

    • 当基类方法和接口方法的特征签名(方法的名称、参数顺序以及参数类型)一样时,导出类优先实现基类方法

9.5 通过继承来扩展接口

  • 扩展接口方法

    • 接口中 implements 接口
    • 接口使用 extends 引用多个基类接口;原因:类多重继承时,如果被继承类中存在相同方法则无法判断调用方法。接口允许多重继承,因为都是抽象方法

      // 继承多个接口的接口 
      public interface Human extends CanJump,CanRun,CanSay {void CanSleep();
      }
      
      public interface CanJump {void jump();
          void fastJump();}
      
      public interface CanRun {void run();
          void fastRun();}
      
      public interface CanSay {void say();
          void fastSay();}

9.5.1 组合接口时的名字冲突

避免使用不同接口中使用相同的方法名

9.6 适配接口

9.7 接口中的域

接口中的任何域都是自动 static,final,public

因此在 java SE5 之前存在使用接口域创建 enum 类型的变量

9.7.1 初始化接口中的域

  • 规则

    • 不能是空 final
    • 可以是非常量表达式 <!– 比如通过随机数赋值 –>

9.8 嵌套接口

  • 规则

    • 接口中可以嵌套在类或者其他接口中
    • 接口中的元素都必须是 public,不能声明为 private,因此接口嵌套在接口中,嵌套的接口必须为 public
    • 类中嵌套接口,接口可以是 private 类型
  • 实现

    <!– 类嵌套接口 –>

    class A {
        private interface D{void f();
        };
        private class DImp implements D{@Override public void f() {};}
        public class DImp2 implements D{@Override public void f(){};}
    }

    <!– 接口嵌套接口 –>

    interface A{
    // 接口默认是 abstract,不能是 private,因为接口中元素只能是 public
    //public abstract interface B{
        interface B{public static final int num = 50;}

    <!– 接口嵌套类 –>

    interface C{class D{}
    }

9.9 接口与工厂

1. 工厂方法设计模式

  • 原理:在工厂对象上调用类的创建方法,该工厂对象生成接口的某个实现的对象,并且可以使用多态
  • 实现

    <!– 接口 –>

    // 接口
    public interface Game {void play();
    }
    
    // 工厂接口
    public interface GameFactory {Game getGame();
    }

    ​ <!– 实现类 –>

    // 硬币游戏类
    class CoinGame implements Game{@Override public void play() {System.out.println("This is coin game");
        }
    }
    // 骰子游戏类
    public class DiceGame implements Game{@Override public void play() {System.out.println("This is dice game");
        }
    }
    
    // 工厂类
    public class GameFactoryCoin implements GameFactory {@Override public Game getGame() {return new CoinGame();
        }
    }
    
    public class GameFactoryDice implements GameFactory {@Override public Game getGame() {return new DiceGame();
        }
    }

    <!– 测试类 –>

    public class Test19 {
        // 传入工厂对象
        static void playGame(GameFactory gameFactory){Game game = gameFactory.getGame();
            game.play();}
        public static void main(String[] args) {playGame(new GameFactoryCoin());
            playGame(new GameFactoryDice());
        }
    }

正文完
 0