面向对象(Object Oriented)
面向对象是一种思想,是基于面向过程而言的,就是说面向对象是将功能等通过对象来实现,将功能封装进对象之中,让对象去实现具体的细节;这种思想是将数据作为第一位,而方法或者说是算法作为其次,这是对数据一种优化,操作起来更加的方便,简化了过程。
面向对象有三大特征:封装性、继承性、多态性,其中封装性指的是隐藏了对象的属性和实现细节,仅对外提供公共的访问方式,这样就隔离了具体的变化,便于使用,提高了复用性和安全性。对于继承性,就是两种事物间存在着一定的所属关系,那么继承的类就可以从被继承的类中获得一些属性和方法;这就提高了代码的复用性。继承是作为多态的前提的。多态是说父类或接口的引用指向了子类对象,这就提高了程序的扩展性,也就是说只要实现或继承了同一个接口或类,那么就可以使用父类中相应的方法,提高程序扩展性,但是多态有一点不好之处在于父类引用不能直接访问子类中的成员属性。
一、三大特性
1.封装
所谓封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。封装是面向对象的特征之一,是对象和类概念的主要特性。
简单的说,一个类就是一个封装了数据以及操作这些数据的代码的逻辑实体。在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问。通过这种方式,对象对内部数据提供了不同级别的保护,以防止程序中无关的部分意外的改变或错误的使用了对象的私有部分。
- 前提:对特有非静态的成员属性与成员方法进行封装,对外开操作接口
- 优点:将变化隔离、便于使用、提高复用性、提高安全性
- 缺点:将不需要对外提供的内容隐藏起来;把属性隐藏,提供公共方法对其访问
2.继承
所谓继承是指可以让某个类型的对象获得另一个类型的对象的属性的方法。它支持按级分类的概念。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”。继承的过程,就是从一般到特殊的过程。
要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。继承概念的实现方式有二类:实现继承与接口继承。实现继承是指直接使用基类的属性和方法而无需额外编码的能力;接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力;
在类的继承关系中成员方法的覆盖遵循一定的规则:
- 当前父类功能已经不满足与当前需求时需要定义子类并复写父类方法,此时复写(当子类方法与父类方法同名时编译器即判断该现象为父类方法的复写)的方法声明、参数列表与父类相同唯独方法体需要从新定义,需要注意的是子类中复写的方法的访问权限描述需要大于或等于父类中被复写的方法,抛出的异常要小于父类的异常范围。需要声明的是覆盖只体现在方法上,成员变量不存在覆盖现象。
- 当父类出现静态方法需要覆盖时,则子类中的对应方法也需要是静态的,非静态方法不能被静态方法覆盖,静态方法也不能被非静态方法覆盖。
- 前提:类继承、接口继承
- 优点:子类可以复用父类成员,提高程序灵活性
- 缺点:不能多继承,难以提高扩展性
3.多态
所谓多态就是指一个类实例的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。重写会产生多态但重载并不会产生多态,因为重载时JVM提供的语言特性,表面上函数名相同但底层JVM会产生不同的函数名。
多态总体上分为:编译时的多态(静态多态)和运行时的多态(动态多态),多态中成员的属性属于静态绑定,方法属于动态绑定,Fu f = new Zi();
- 对于成员变量:倘若子父类中都存在同名属性时,(多态调用)使用f调用时只会调用父类中的属性即便父类中没有该属性也不会调用子类中的属性,也就是说成员属性并不具有多态的特性,即便子类进行了覆盖也只能使静态绑定(只会调用对象的引用类型所对应的成员变量,编译时与运行时都根据引用类型中的属性)
- 对于成员函数:子父类中出现同名函数多态调用时f会先查找所属类中的方法倘若所属类中没有对应方法,这时才会查找引用类型中对应的方法(编译时根据引用类型中的方法,运行时根据所属类中的方法)
- 对于静态成员:子类会继承父类中的静态成员,不管是覆盖还是不覆盖,在多态调用时f只会去父类中找所需的静态成员,因为静态成员属于类与对象无关,所以这类调用只与应用类型有关(编译与运行都只与引用类型相关)
根据Cardelli 和Wegner 的结论还可以把多态细分为以下4类:
- 参数多态:采用参数化模板,通过给出不同的类型参数,使得一个结构有多种类型。如 C++语言中的函数模板和类模板属于参数多态。参数多态又叫静态多态,它的执行速度快,异常少,调用在编译时已经确定。参数多态是应用比较广泛的一种多态,被称为最纯的多态。
- 包含多态:在许多语言中都存在,最常见的例子就是子类型化,即一个类型是另外一个类型的子类型。一般需要进行运行时的类型检查,属于动态多态。包含多态的基础是虚函数。虚函数是引入了派生概念后用来表现基类和派生类的成员函数之间的一种关系。
- 过载多态:同一个名字在不同的上下文中所代表的含义不同。典型的例子是运算符重载和函数重载,属于静态多态。
- 强制多态:编译程序通过语义操作,把操作对象的类型强行加以变换,以符合函数或操作符的要求。程序设计语言中基本类型的大多数操作符,在发生不同类型的数据进行混合运算时,编译程序一般都会进行强制多态。程序员也可以显示地进行强制多态的操作。如 int+double,编译系统一般会把 int 转换为 double,然后执行 double+double 运算,这里的int->double 的转换,就实现了强制多态,即可是隐式的,也可显式转换。强制多态属于静态多态。
- 前提:继承父类或实现接口、覆盖方法、父类或接口引用指向子类对象
- 优点:极大地提高了程序的可扩展性
- 缺点:父类引用不能直接取得子类成员属性,而且父类并不能调用子类特有的方法