面向接口编程指不关注对象的具体类型,而仅仅针对超类型中的“契约方法”来编写程序,以极大地减少子系统实现之间的相互依赖关系,
面向接口编程,而不是面向实现编程
鸭子类型
: “如果它走起路来像鸭子,叫起来也是鸭子,那么它就是鸭子。”
示例
面向接口编程在面向对象语言中可以使用抽象类和 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
的作用主要都是以下两点:
- 通过向上转型来隐藏对象的真正类型,以表现对象的多态性。
- 约定类与类之间的一些契约行为。
我们只需要根据约定类的结构进行编程即可,无需关心实际的实例是哪个类的,以及它有没有这个方法。