上一次在使用Java开始面向对象的编程这篇文章中我们学习了一个编程语言要真正成为面向对象的它应该支持信息隐藏/封装多态继承和动态绑定另外我们知道了Java完全支持这些功能而且知道了因为Java是一种解释性的语言并运行在虚拟机的内部所以由Java写成的任何程序都可以在任何支持 Java虚拟机(JVM)的操作系统上运行我们还明白了对象是代表现实生活中事物的软件编程模型以及对象是由它们的状态和行为定义的最后我们知道了Java中除了原始数据对象以外一切都是对象 因为这种程序设计风格中的这许多内容都和对象以及类有关我们将在下面进一步的考察它们 对象详论 使用对象的一个关键是当你在浏览系统分析文档或者设计文档的时候如何来确定它们因为对象一般代表人地方或者事物所以一个确定对象的基本的方法就是找出句子中所使用的名词这里有一个简单的例子在句子一个顾客可以拥有多于一个的银行帐号我们就确定了两个对象客户和帐号在句子小猫喵喵叫中我们能够确定一个对象猫 类详论 前面我们学习了一个类是定义了对象如何动作以及当对象创建或者说实例化的时候应该包含些什么的实体在对动物的讨论中我们可以说狗儿汪汪叫猫喵喵叫鸭子嘎嘎叫确定句子中的对象我们就得到了狗猫和鸭子至于汪汪叫喵喵叫嘎嘎叫那都是我们对象发出的行为动作 要实现这些对象我们需要创建三个对象分别叫DogCat和Duck要实现它们的行为我们可以为每一个这些对象创建代表每个对象发出的声音的方法而且我们把这个方法叫做speak或者如果我们发挥想象力的话还可以把这个方法叫做sayHello 在程序的上下文中为了演示这些概念让我们修改上篇文章中的HelloWorld程序添加这三个新对象并给它们中的每一个添加sayHello方法如下所示: public class HelloWorld { public static void main(String[] args) { Dog animal = new Dog(); Cat animal = new Cat(); Duck animal = new Duck(); animalsayHello(); animalsayHello(); animalsayHello(); } } class Dog { public void sayHello() { Systemoutprintln(Bark); } } class Cat { public void sayHello() { Systemoutprintln(Meow); } } class Duck { public void sayHello() { Systemoutprintln(Quack); } } 在编译并运行了这个程序以后输出应该如下: Bark Meow Quack 看看我们的程序我们马上就注意到了一些事情:每个对象代表了一种动物而每个对象实现了一个相同的方法sayHello假设我们想要给对象更多的功能以及用来代表对象所指的动物的方法和属性比方说我们可以添加一个方法来确定一个动物是不是哺乳类的或者我们添加一个方法来确定一个动物是不是肉食性的我们可以通过给每一个对象添加这两种方法来实现或者我们也能够使用OOP的两个最强大的功能:继承和多态 因为所有的对象都代表一个对象所以我们将创建一个被称为基类或是超类的类它的名字是Animal我们然后可以让我们的对象从Animal类继承相同的特点并强制每个对象只实现与Animal类不同的功能 Java用extends关键字指明一个类从另一个继承让我们利用继承和多态的概念获得代码重用的好处来重建我们的程序并使得每个对象只实现与基类Animal不同的功能: 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() + is carnivorous: +animalisCarnivorous() + is a mammal: +animalisAMammal()); Systemoutprintln(A cat says +animalgetHello() + is carnivorous: +animalisCarnivorous() + is a mammal: +animalisAMammal()); Systemoutprintln(A duck says +animalgetHello() + is carnivorous: +animalisCarnivorous() + is a mammal: +animalisAMammal()); } } abstract class Animal { public boolean isAMammal() { return(true); } public boolean isCarnivorous() { return(true); } abstract public String getHello(); } class Dog extends Animal { public String getHello() { return(Bark); } } class Cat extends Animal { public String getHello() { return(Meow); } } class Duck extends Animal { public boolean isAMammal() { return(false); } public boolean isCarnivorous() { return(false); } public String getHello() { return(Quack); } } 在编译并运行我们的程序以后输出应该如下: A dog says Bark is carnivorous: true is a mammal: true A cat says Meow is carnivorous: true is a mammal: true A duck says Quack is carnivorous: false is a mammal: false 看看我们的例子你将发现我们定义了一个叫做Animal的新类它定义了三个方法:isAMammal isCarnivorous 和 getHello你一概还注意到了我们在每个现存的类申明的前面都添加了extends Animal这个语句这个语句告诉编译器这些对象是Animal类的子类 因为方法isAMammal 和 isCarnivorous 都返回 true所以Dog和Cat类用不着重新实现即重载这两个方法但是鸭子既不是哺乳动物又不是肉食性的所以Duck类需要重载这两种方法来返回正确的值我们所有的对象都以自己独特的方式说hello所以它们都需要重载getHello方法因为每种动物说hello的方式都不同所以我们在基类中将getHello方法申明为抽象的而且我们没有给这个方法一个函数体这就迫使Animal的每一个子类重载getHello方法并根据每一个特定动物的需要来定义它 因为我们将getHello方法申明为虚拟的我们就不能直接实例化Animal对象因此我们需要将Animal类也申明为抽象的我们通过在Animal类定义的开始行添加abstract关键字来实现这一点子类重载它们基类的方法的能力就是多态多态使得子类能够使用基类的方法或是在这些方法不足的时候重载它们这就实现了代码重用加快了代码的实现过程而且它还隔离和程序中的bug使得程序的维护更容易 总结 在本文中我们学习了如何确定潜在的对象我们还学习了如何使用继承和多态来加快我们的代码实现过程并隔离错误这使得代码的维护过程更加容易下一次我们将展开讨论多态和继承的概念并开始我们对动态绑定的讨论 |