Javascript 面向接口编程

1,523 阅读2分钟

面向接口编程指不关注对象的具体类型,而仅仅针对超类型中的“契约方法”来编写程序,以极大地减少子系统实现之间的相互依赖关系,

面向接口编程,而不是面向实现编程

鸭子类型: “如果它走起路来像鸭子,叫起来也是鸭子,那么它就是鸭子。”

示例

面向接口编程在面向对象语言中可以使用抽象类和 interface 来实现。

  • java抽象类实现
// 动物抽象类
public abstract class Animal {
    abstract void makeSound(); // 抽象方法
}
// 鸭子类
public class Duck extends Animal{
    public void makeSound(){
        System.out.println( "嘎嘎嘎" );
    }
}
// 鸡类
public class Chicken extends Animal{
    public void makeSound(){
        System.out.println( "咯咯咯" );
    }
}
public class AnimalSound{
    // 接收 Animal 类型的参数,而非 Duck 类型或 Chicken 类型
    public void makeSound( Animal animal ){ 
        animal.makeSound();
    }
}
// 鸭子和鸡都通过一个方法发出叫声,Animal抽象类就可以当作接口
public class Test {
    public static void main( String args[] ){
        AnimalSound animalSound = new AnimalSound ();
        Animal duck = new Duck();// 向上转型
        Animal chicken = new Chicken(); // 向上转型
        animalSound.makeSound( duck ); // 输出:嘎嘎嘎 
        animalSound.makeSound( chicken ); // 输出:咯咯咯
    }
} 

  • java接口实现
// 动物接口
public interfac Animal {
    abstract void makeSound(); // 抽象方法
}
// 鸭子类
public class Duck implements Animal{
    public void makeSound(){
        System.out.println( "嘎嘎嘎" );
    }
}
// 鸡类
public class Chicken implements Animal{
    public void makeSound(){
        System.out.println( "咯咯咯" );
    }
}
public class AnimalSound{
    // 接收 Animal 类型的参数,而非 Duck 类型或 Chicken 类型
    public void makeSound( Animal animal ){ 
        animal.makeSound();
    }
}
// 鸭子和鸡都通过一个方法发出叫声,Animal就是接口
public class Test {
    public static void main( String args[] ){
        AnimalSound animalSound = new AnimalSound ();
        Animal duck = new Duck();// 向上转型
        Animal chicken = new Chicken(); // 向上转型
        animalSound.makeSound( duck ); // 输出:嘎嘎嘎 
        animalSound.makeSound( chicken ); // 输出:咯咯咯
    }
} 

  • javascript实现
class Duck {
    makeSound() {
        console.log('嘎嘎嘎');
    }
}
class Chicken {
    makeSound() {
        console.log('咯咯咯');
    }
}
class AnimalSound{
    makeSound(animal){ 
        animal.makeSound();
    }
}

const animalSound = new AnimalSound ();
const duck = new Duck();// 向上转型
const chicken = new Chicken(); // 向上转型
animalSound.makeSound(duck); // 输出:嘎嘎嘎 
animalSound.makeSound(chicken); // 输出:咯咯咯
  • 使用Typescript来进行类型检查

为了防止鸭子类或者鸡类没有实现makeSound方法导致报错,一方面可以写参数检查,另一方面可以借助typescript的接口Interface来实现。

interface Animal {
    makeSound: Function;
}
class Duck {
    makeSound() {
        console.log('嘎嘎嘎');
    }
}
class Chicken {
    makeSound() {
        console.log('咯咯咯');
    }
}
class AnimalSound{
    makeSound(animal: Animal){ 
        animal.makeSound();
    }
}

const animalSound = new AnimalSound ();
const duck: Animal = new Duck();// 向上转型
const chicken: Animal = new Chicken(); // 向上转型
animalSound.makeSound(duck); // 输出:嘎嘎嘎 
animalSound.makeSound(chicken); // 输出:咯咯咯

总结

抽象类和 interface 的作用主要都是以下两点:

  • 通过向上转型来隐藏对象的真正类型,以表现对象的多态性。
  • 约定类与类之间的一些契约行为。

我们只需要根据约定类的结构进行编程即可,无需关心实际的实例是哪个类的,以及它有没有这个方法。

参考