原文地址:
http://hi.baidu.com/dingzhoufang/blog/item/1f93026d1de7c0fd431694c4.html
继承性、封装性和多态性是面向对象的三个核心概念,下面就来看看在C++和Java中
是如何实现面向对象机制的:
一 继承性
面向对象方法中的继承机制使子类可以自动地拥有父类的全部属性和操作(方法)。
(1)C++
派生类是C++中实现继承性的语法概念。派生类的一般声明语法为:
Class 派生类名 :继承方式 基类名1,继承方式 基类名2,…,继承方式 基类名n
{
派生类成员声明;
};
其中:继承方式有public, protected, private三种,默认值为private。类的继承方式指定了派生类成员以及类外对象对于从基类继承来的成员的访问权限。
在C++中,一个派生类(子类)可以同时有多个直接基类(父类),即C++支持多继承。
当然一个派生类(子类)也可以只有一个直接基类(父类),称此种情况为单继承。在派生的过程中,派生出来的新类也同样可以作为基类再继续派生新的类。一个基类可以同时派生出多个派生类,即一个类可以同时作为多个派生类的基类。
(2)java
在java语言中,子类对父类的继承是通过在类的声明中,用关键字extends来说明的。其语法形式为:
[ClassModifier] class ClassName extends SuperClassName [implements interface]
{
子类的属性和方法;
}
其中:关键字extends说明要声明的类需要继承父类的属性和行为,SuperClassName是被继承的父类的名称。
Java 要求声明的每个类都有父类,当没有显示的指定父类时,父类隐含为java.lang.Object。一个父类可以同时拥有多个子类,这是该父类实际上是所有子类的公共属性和方法的集合,而每一个子类则是父类的特殊化,是在公共属性的基础上的功能(方法),内涵(属性(变量))的扩展和延伸。
Java不支持类的多重继承,只支持类的单继承。即每个子类只能有一个直接父类。类的层次结构为树状结构,Object类为树的根节点。
二 封装性
封装是指将从现实世界中抽象得到的数据成员和代码成员相结合,形成一个有机的整体,即将数据与操作数据的行为进行有机的结合。在面向对象程序设计中,可以通过封装,将一部分成员作为类与外部的接口,将其他的成员隐藏起来,以达到对数据访问权限的有效控制。
(1) C++
在C++中,封装是借助于类(Class)来实现的。对象是类类型的数据,即为类的实例。C++中声明类的语法如下:
Class 类名称{
Public :
外部接口;
Protected:
保护型成员;
Private:
私有成员;
};
(2) java
在java中,封装也是借助于类(Class)来实现的。对象是类类型的数据,即为类的实例。java中声明类的语法如下:
[public][abstract | final] class 类名称 [extends 父类名称] [implements 接口名称列表]{
变量成员声明及初始化;
方法声明及方法实现(方法体);
}
其中:
Class是关键字,表明其后声明的是一个类。
Class前的修饰符可以有多个,用来限定类的使用方式。Public为存取控制符,表明此类为公有类,abstract指明此类为抽象类,final指明此类为终结类。
类名称是用户为该类所起的名字,它应该是一个合法的标识符,并尽量遵从命名约定。
Extends是关键字,如果所声明的类是从某一个父类派生而来的,那么父类的名字应写在extends之后。
Implements是关键字,如果所声明的类要实现某些接口,那么接口的名字应写在implements之后。
类的声明体中有两部分,一部分是数据成员变量的声明及初始化,可以有多个;另一部分是成员方法的声明及实现,也可以有多个。
三 多态性
多态的主要意思是:“一个名字,多种语义;或相同的界面,多种实现”。多态性是一种方法,使在多个类中可以定义一个操作和属性名,并在每一个类中有不同的实现。正式的说法就是:同一个消息被不同的对象接收时,可产生不同的动作或执行结果,即每个对象将根据自己所属类中定义的操作执行。
(1) C++
C++中的多态性有两种情况:一种是编译时多态性,它是由重载函数支持的,强调的是函数名相同,函数参数和函数体不同。函数调用与函数体的匹配在编译时就能确定。另一种是运行时多态性,这是由虚函数支持的,它强调的是完全单一的界面,不同的实现;即函数名,返回类型,函数参数类型,顺序,个数完全相同,但函数体不同。这种情况下,函数调用与函数体的匹配在运行时才能确定。
函数重载:两个或两个以上的函数,取相同的函数名,但是形参的个数或者类型不同,编译器根据实参和形参的类型及个数的最佳匹配,自动确定调用哪一个函数。C++允许功能相近的函数在相同的作用域内以相同的函数名定义(不同的作用域内的同名函数不是重载,此时其生命周期就不一样),从而形成重载。
虚函数:是使用virtual关键字来限定的非静态的成员函数,虚函数经过派生之后,在类簇中就可以实现运行过程中的多态。如果需要通过基类的指针指向派生类的对象,并访问某个与基类同名的成员(若为函数,其原型完全相同),那么首先在基类中将这个同名函数定义为虚函数。这样,就可以通过基类类型的指针,来访问该同名的函数,使得属于不同派生类的不同对象产生不同的行为,从而实现运行过程的多态。虚函数定义语法如下:
Virtual 函数返回值类型 函数名称(形参列表){
函数体(函数的实现);
}
虚函数的声明只能出现在类声明的函数原型声明之前,而不能在函数体实现的时候才声明。只要在基类中声明,而不要在派生类中再声明。若派生类没有显式的给出虚函数声明,此时系统会自动的按照以下规则来判断一个函数是不是虚函数:
.该函数是否与基类的虚函数有相同的名称;
.该函数是否与基类的虚函数有相同的参数个数及相同的对应参数类型;
.该函数是否与基类的虚函数有相同的返回值或者满足赋值兼容规则的指针,引用型的返回值。
如果从名称,参数和返回值三方面检查之后,派生类的函数满足了上述条件,就被自动确定为虚函数。
运行过程中的多态需要满足以下三个条件:①类之间应满足赋值兼容规则(指在需要基类对象的任何地方都可以使用公有派生类的对象来代替,这种代替包括:派生类的对象可以赋值给基类的对象;派生类的对象可以初始化基类的引用;派生类对象的地址可以赋给指向基类的指针。在替代之后,派生类的对象就可以作为基类的对象来使用,但只能使用从基类继承来的成员,即在基类出现的场合可以使用派生类进行代替,但是代替之后派生类仅仅发挥出基类的作用);②要在基类中声明虚函数;③要由成员函数来调用或者是通过指针,引用来访问虚函数。(如果是使用对象名来访问虚函数,则联编在编译过程中就可以进行(静态联编),而无需在运行过程中进行)
(2) java
在java 中,利用向上塑型(type-casting)技术(类型转换),任何一个子类的对象或引用变量都可以被塑型((自动的)类型转换)为其父类的对象,即一个父类的对象或引用变量可以指向不同的子类对象,而利用动态绑定(dynamic Binding)技术(可以在程序运行期间判断对象的类型,并根据其所属的实际类型分别调用其真实类型的适当的方法,此时方法的调用与该方法的主体连接在一起(绑定binding)),可以在运行时根据父类对象或引用变量所指对象的实际类型执行相应的子类中的方法,从而实现多态性。