OOP: 继承以及多态

原创 2004年07月05日 19:57:00

Wednesday, October 10 2001 8:30 PM

在"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 animal1 = new Dog();
Cat animal2 = new Cat();
Duck animal3 = new Duck();

System.out.println("A dog says " +animal1.getHello()
+", when scared says: " +animal1.getHello(Animal.SCARED)
+", is carnivorous: " +animal1.isCarnivorous()
+", is a mammal: " +animal1.isAMammal());
System.out.println("A cat says " +animal2.getHello()
+", when comforted says: " +animal2.getHello(Animal.COMFORTED)
+", is carnivorous: " +animal2.isCarnivorous()
+", is a mammal: " +animal2.isAMammal());
System.out.println("A duck says " +animal3.getHello()
+", when scared says: " +animal3.getHello(Animal.SCARED)
+", is carnivorous: " +animal3.isCarnivorous()
+", is a mammal: " +animal3.isAMammal());
}
}

abstract class Animal
{
public static final int SCARED = 1;
public static final int COMFORTED = 2;

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(4);
}

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(4);
}

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(2);
}

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的变量作用域/可见域规则来控制方法和属性的暴露问题.

OOP-----封装,继承,多态

1.封装( public protected  private)      可以把封装理解成隐藏,我们所定义的类里面的成员有时我们不能让用户或者没有权限的客户去修改他们,我们要想办法让里面的成员得到...
  • qq_32080545
  • qq_32080545
  • 2016年06月19日 15:10
  • 623

Lua下通过元表模拟OOP编程,继承多态

Lua本身是没有以明确的定义来支持OOP编程的,但是我们却可以通过Lua本身提供的一些特性来间接实现简单的面向对象的编程。...
  • yue7603835
  • yue7603835
  • 2014年12月09日 10:16
  • 3503

JAVA—OOP之多态

JAVA—OOP之多态   水,汽,冰就是一个物体在不同条件下的不同种状态   1、什么是多态? A:生活中的多态 就好比在学校没老师上自习课一样,此时每种人都有不同的状态,有的认真做作业,有的玩手机...
  • tanmin_tm
  • tanmin_tm
  • 2016年10月22日 18:30
  • 216

php面向对象(OOP)—多态

多态是除封装和继承之外的另一个面象对象的三大特性之一,我个人看来PHP中虽然可以实现多态,但和c++还有Java这些面向对象的语言相比,多 态性并不是那么突出,因为PHP本身就是一种弱类型的语言,不存...
  • guoshaoqing001
  • guoshaoqing001
  • 2015年06月05日 15:00
  • 1423

Python 进阶_OOP 面向对象编程_组合与继承

目录 目录 前言 组合 派生 前言 我们定义一个类是希望能够把类当成模块来使用, 并把类嵌入到我们的应用代码中, 和其他的数据类型/逻辑执行流结合使用. 一般来说我们可以使用两种...
  • Jmilk
  • Jmilk
  • 2016年11月06日 13:14
  • 2354

如何理解封装、继承和多态

封装:  封装是实现面向对象程序设计的第一步,封装就是将数据或函数等集合在一个个的单元中(我们称之为类)。被封装的对象通常被称为抽象数据类型。   封装的意义:   封装的意义在于保护或者防止代...
  • c_w_d
  • c_w_d
  • 2016年10月31日 14:36
  • 10022

继承与多态的区别

想起有一次面试,一位技术部领导问"面向对象的基本特征说一下".于是我说了"封装,继承,多态",然后有啰啰嗦嗦的说了一些对这些知识点的理解.然而,当我说完,面试官说"其实面向对象的基本特征可以总结为两个...
  • baidu_33714003
  • baidu_33714003
  • 2016年08月23日 14:31
  • 6510

【c++知识归纳】继承与多态(一)

c++是基于面向对象的编程语言,面向对象的三大特性为:封装、继承和多态。本文将我对继承与多态的理解进行了总结归纳,这部分内容对于学习c++编程语言是非常重要的,文章加入我的个人理解,希望能给大家带来帮...
  • XHfight
  • XHfight
  • 2016年08月24日 02:45
  • 1247

继承、多态,重载、重写的区别与总…

继承、多态,重载、重写的区别与总结 一道必考的JAVA核心面试题,什么是多态?它的实现机制是什么呢?重载和重写的区别在那里?这就是这一次我们要回顾的四个十分重要的概念:继承、多态、重载和重写。 ...
  • li19236
  • li19236
  • 2014年11月25日 18:10
  • 1866

OC学习篇之---类的三大特性(封装,继承,多态)

之前的一片文章介绍了OC中类的初始化方法和点语法的使用:http://blog.csdn.net/jiangwei0910410003/article/details/41683873,今天来继续学习...
  • jiangwei0910410003
  • jiangwei0910410003
  • 2014年12月04日 22:20
  • 30888
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:OOP: 继承以及多态
举报原因:
原因补充:

(最多只允许输入30个字)