在OOP简介:理解类和对象这篇文章中我们讨论了继承和多态性的好处我们还粗略的学习了如何扩展基类定义子类继承基类中合适的行为和属性而重载那些并不适合的行为和属性这种方式能够削减代码宏余以及错误的堆积 现在我们将更深入的考察多重继承性以及Java是如何处理它的我们还将通过学习动态绑定来学习多态性 深入继承性 一些面向对象的语言提供叫做多重继承的特点当一个对象需要从多于一个的基类继承行为和属性的时候这是有价值的多重继承在有些情况下是复杂的例如假设我们需要定义一个基类Animal然后是Animal的两个子类LandAnimal 和 WaterAnimal现在我们想要定义一个类来代表青蛙青蛙是两栖动物所以我们自然会想到定义Frog类从LandAnimal和WaterAnimal类继承这使得Frog类能够同时从LandAnimal 和WaterAnimal类继承所需的行为和属性 初看起来这是相当简单的;但是让我们为Animal添加一个叫做LivingEnvironment的属性并用方法getLivingEnvironment来返回它我们假设LandAnimal 和 WaterAnimal类都重载了这个方法来实现特殊的功能LandAnimal将返回Land作为它的LivingEnvironment属性的值而WaterAnimal将返回Water作为它的LivingEnvironment属性的值现在当我们将Frog类作为LandAnimal 和 WaterAnimal 子类实现的时候想要得到Frog的LivingEnvironment属性值这时将遇到一个麻烦:Frog类的getLivingEnvironment方法是返回Land值呢还是Water值?答案取决于编译器如何处理多重继承 我在前面的文章里就已经说过Java不支持多重继承但它确实允许一个对象通过使用叫做接口的功能拥有多个特性下面的例子显示了定义LandAnimal的接口的可能的定义代码: public interface LandAnimal { public int getNumberOfLegs(); public boolean hasATail(); } 一个使用接口的类在类定义语句的开始添加implements+接口名例如在Java中我们会以下面的方式定义Frog类: public class Frog extends Animal implements LandAnimal WaterAnimal 接口并没有什么实际的功能;相反它的作用是联系使用者和实现了这个接口的对象接口保证了对象实现接口定义的方法而且一个实现接口的对象能够在运行时被强制转换成接口类型例如使用上面的Frog定义并且假设LandAnimal类定义了一个叫做getNumberOfLegs的方法而WaterAnimal定义了一个叫做hasGills的方法那么一个Frog类的实例可以在运行时被强制转换成LandAnimal或WaterAnimal对象: Frog aFrog = new Frog(); int legCount = ((LandAnimal)aFrog)getNumberOfLegs(); Boolean gillFlag = ((WaterAnimal)aFrog)hasGills(); 注意Forg为什么能够被强制转换成一个LandAnimal对象即使实际的LandAnimal对象并没有被创建这使得我们能够在运行时以其带有的任何身份调用一个对象这就是所谓的动态绑定或运行时绑定 深入多态性 Java使用动态绑定来使多态成为可能它指的是Java用来在运行时选择调用的方法或对象的机制重载构成了了Java中的一种特殊的多态机制它表现在当一个类的两个或者两个以上的方法拥有相同的名字但是不同的参数列表或者说方法签名一个方法的签名指的是方法的名字以及参数的类型和数目类的每一个方法都有与之相关的唯一的签名类可以有多个名字相同的方法只要它们的参数列表是唯一的例如我们能够为Animal类定义两个名字为getHello的方法用其中一个方法来获得动物通常的叫声而用另一个获得当动物被惊吓或是抚摩的时候的叫声我们将给每一个方法唯一的签名: public String getHello(); public String getHello(int mood); 现在让我们修改例子程序来将我们讨论的一些概念付诸实践: public class HelloWorld { public static void main(String[] args) { Dog animal = new Dog(); Cat animal = new Cat(); Duck animal = new Duck(); Systemoutprintln(A dog says +animalgetHello() + when scared says: +animalgetHello(AnimalSCARED) + is carnivorous: +animalisCarnivorous() + is a mammal: +animalisAMammal()); Systemoutprintln(A cat says +animalgetHello() + when comforted says: +animalgetHello(AnimalCOMFORTED) + is carnivorous: +animalisCarnivorous() + is a mammal: +animalisAMammal()); Systemoutprintln(A duck says +animalgetHello() + when scared says: +animalgetHello(AnimalSCARED) + is carnivorous: +animalisCarnivorous() + is a mammal: +animalisAMammal()); } } abstract class Animal { public static final int SCARED = ; public static final int COMFORTED = ; public boolean isAMammal() { return(true); } public boolean isCarnivorous() { return(true); } abstract public String getHello(); abstract public String getHello(int mood); } interface LandAnimal { public int getNumberOfLegs(); public boolean hasATail(); } interface WaterAnimal { public boolean hasGills(); public boolean laysEggs(); } class Dog extends Animal implements LandAnimal { // 重载父类的方法 public String getHello() { return(Bark); } public String getHello(int mood) { switch (mood) { case SCARED: return(Growl); case COMFORTED: return(); } return(Bark); } // LandAnimal 接口的实现 public int getNumberOfLegs() { return(); } public boolean hasATail() { return(true); } } class Cat extends Animal implements LandAnimal { // 重载父类的方法 public String getHello() { return(Meow); } public String getHello(int mood) { switch (mood) { case SCARED: return(Hiss); case COMFORTED: return(Purr); } return(Meow); } // LandAnimal 接口实现 public int getNumberOfLegs() { return(); } public boolean hasATail() { return(true); } } class Duck extends Animal implements LandAnimal WaterAnimal { // 重载父类的方法 public String getHello() { return(Quack); } public String getHello(int mood) { switch (mood) { case SCARED: return(Quack Quack Quack); case COMFORTED: return(); } return(Quack); } public boolean isAMammal() { return(false); } public boolean isCarnivorous() { return(false); } // WaterAnimal 接口实现 public boolean hasGills() { return(false); } public boolean laysEggs() { return(true); } // LandAnimal 接口实现 public int getNumberOfLegs() { return(); } public boolean hasATail() { return(false); } } 程序执行后输出的结果如下: A dog says Bark when scared says: Growl is carnivorous: true is a mammal: true A cat says Meow when comforted says: Purr is carnivorous: true is a mammal: true A duck says Quack when scared says: Quack Quack Quack is carnivorous: false is a mammal: false 总结 综合继承多态和接口的概念提供了一组强大的编程工具允许我们重用代码隔离错误的发生并获得动态/运行时绑定带来的好处在下一篇文章里我们将讨论如何使用Java的变量作用域/可见域规则来控制方法和属性的暴露问题 |