互联网推广网站建设,免费php网站模板,网站介绍页面,做外贸哪几个网站好OOP
【面向对象程序设计】#xff08;OOP#xff09;与【面向过程程序设计】在思维方式上存在着很大的差别。【面向过程程序设计】中#xff0c;算法是第一位的#xff0c;数据结构是第二位的#xff0c;这就明确地表述了程序员的工作方式。首先要确定如何操作数据#…OOP
【面向对象程序设计】OOP与【面向过程程序设计】在思维方式上存在着很大的差别。【面向过程程序设计】中算法是第一位的数据结构是第二位的这就明确地表述了程序员的工作方式。首先要确定如何操作数据然后再决定如何组织数据以便于数据操作。而【面向对象程序设计】却调换了这个次序【面向对象程序设计】将数据放在第一位然后再考虑操作数据的算法。
对于一些规模较小的问题将问题分解为过程的开发方式比较理想。而面向对象更加适用于解决规模较大的问题。
面向对象程序设计是一种编程范式或编程风格。面向对象的程序是由类和对象组成的以类和对象作为组织代码的基本单元并将封装、抽象、继承、多态这四个特性作为程序设计和实现的基础。
面向对象程序设计语言是【支持类和对象的语法机制。并有现成的语法机制能方便地实现 OOP 的四大特性封装、抽象、继承、多态】的编程语言。
OOP 的四大特性
对于 OOP 的四大特性我们需要知道每一个特性的如下知识
xxx 特性的含义为了实现 xxx 特性需要程序设计语言提供一定的语法机制来支持。对于这四大特性尽管大部分面向对象程序设计语言都提供了相应的语法机制来支持但不同的编程语言实现这四大特性的语法机制可能会有所不同。xxx 特性存在的意义、好处
封装
封装encapsulation也被称为数据隐藏、数据访问保护。从形式上看封装就是将数据和行为组合在一起中并对对象的使用者隐藏数据的实现方式。
对象中的数据被称为实例域instance field操作数据的过程被称为方法method。对于每个特定的类实例对象都有一组特定的实例域值。这些值的集合就是这个对象的当前状态state。
实现封装的关键在于绝对不能让类中的方法直接地访问其他类的实例域。程序仅通过对象的方法与对象数据进行交互。封装给对象赋予了 “黑盒” 特征这是提高重用性和可靠性的关键。这意味着一个类可以全面地改变存储数据的方式只要仍旧使用同样的方法操作数据其他对象就不会知道或介意所发生的变化。 为了实现封装这个特性需要程序设计语言提供一定的语法机制来支持。这个语法机制就是访问权限控制访问修饰符public、protected、private、default。
在 Java 中封装就意味着所有的实例域都带有 private 访问修饰符私有的实例域并提供带有 public 访问修饰符的域访问器方法和域更改器方法公共的操作方法。
如果实例域带有 public 访问修饰符这就破坏了封装性。因为 public 实例域允许程序中的任何方法对其进行读取和修改。
如果域访问器方法、域更改器方法直接返回了一个可变对象的引用这就破坏了封装性。在 Employee 类中就违反了这个设计原则其中的 getHireDay() 方法返回了一个 Date 类对象。Date 类有一个更改器方法 setTime()可以使用 setTime() 这个方法设置毫秒数。Date 对象是可变的这一点就破坏了封装性。对 d 调用更改器方法就可以自动地改变这个雇员对象的私有状态。
如果域访问器方法、域更改器方法需要返回一个可变对象的引用应该首先对对象进行克隆clone。 对象 clone 指的是存放在另一个位置上的对象副本。 class Employee {private Date hireDay;public Date getHireDay() {return hireDay; // Bad}// ...
}Employee harry . .
Date d harry.getHireDay();
double tenYearsInMilliSeconds 10 * 365.25 * 24 * 60 * 60 * 1000;
d.setTime(d.getTime() - (long) tenYearsInMilliSeconds);
// lets give Harry ten years of added seniority// 修改后的代码
class Employee {public Date getHireDay() {return (Date) hireDay.clone(); // Ok}// ...
}封装存在的意义、封装的好处程序仅通过对象的方法与对象数据进行交互
保护对象数据不被随意修改。可以改变类的内部实现除了该类的方法之外不会影响其他的代码。更改器方法可以执行错误检查而直接对实例域进行赋值将不会进行这些处理。例如setSalary 方法可以检查薪水是否小于 0。
抽象
封装主要讲的是如何隐藏数据、数据访问保护而抽象讲的是如何隐藏方法的具体实现让方法的调用者只需要关心方法提供了哪些功能并不需要知道这些功能是如何实现的。 我们可以借助程序设计语言提供的接口类比如 Java 中的 interface 关键字语法或者抽象类比如 Java 中的 abstract 关键字语法这两种语法机制来实现抽象这一特性。
实际上抽象这个特性是非常容易实现的并不需要非得依靠接口类或者抽象类这些语法机制来支持。换句话说并不是说一定要为实现类抽象出接口类才叫作抽象。即便不编写接口类单纯的实现类本身就满足抽象特性。
之所以这么说那是因为类的方法是通过程序设计语言中的 “函数” 这一语法机制实现的。通过函数包裹具体的实现逻辑这本身就是一种抽象。调用者在调用函数的时候并不需要去研究函数内部的实现逻辑只需要通过函数的命名、注释或者文档了解该函数提供了什么功能就可以直接调用了。比如我们在使用 C 语言的 malloc() 函数的时候并不需要了解它的底层代码是怎么实现的。 抽象存在的意义、抽象的好处
一方面抽象提高了代码的可扩展性、可维护性修改实现不需要改变定义减少了代码的改动范围另一方面抽象是处理复杂系统的有效手段抽象能有效地过滤掉不必要关注的信息。
继承
继承inheritance即 “is-a” 关系是一种用于表示特殊与一般关系的。 例如RushOrder 类由 Order 类继承而来。在具有特殊性的 RushOrder 类中包含了一些用于优先处理的特殊方法以及一个计算运费的不同方法而其他的方法如添加商品、生成账单等都是从 Order 类继承来的。 利用继承人们可以基于已存在的类构造一个新类。继承已存在的类就是复用继承这些类的方法和域。在此基础上还可以添加一些新的方法和域以满足新的需求。
从继承关系上来讲继承可以分为单继承和多继承。有些程序设计语言只支持单继承不支持多重继承比如 Java、PHP、C#、Ruby 等而有些程序设计语言既支持单继承也支持多继承比如 C、Python、Perl 等。
单继承表示一个子类只能继承一个父类多继承表示一个子类可以继承多个父类。 为了实现继承这个特性需要程序设计语言提供一定的语法机制来支持。比如 Java 使用 extends 关键字来实现继承C 使用冒号来实现继承class B : public APython 使用 parentheses() 来实现继承Ruby 使用 来实现继承。 继承存在的意义、继承的好处继承的一个最大好处就是代码复用。假如两个类有一些相同的属性和方法我们就可以将这些相同的部分抽取到基类中让两个子类继承基类。这样两个子类就可以重用基类中的代码避免代码重复写多遍。
不过代码复用这个好处也并不是继承所独有的我们也可以通过其他的方式来解决代码复用的问题比如利用组合关系。
过度的使用继承继承的层次过深、过复杂就会导致代码的可读性、可维护性变差。
可读性变差的原因为了了解一个类的功能我们不仅需要查看这个类的代码还需要按照继承关系一层一层地往上查看“父类、父类的父类……”的代码。可维护性变差的原因子类和父类高度耦合修改父类的代码会直接影响到子类。
多态
一个对象变量可以指向多种实际类型的现象被称为多态polymorphism。在运行时自动地选择调用哪个方法的现象被称为动态绑定dynamic binding。 为了实现多态这个特性需要程序设计语言提供一定的语法机制来支持。
第一个语法机制是程序设计语言要支持继承第二个语法机制是程序设计语言要支持父类的对象变量可以引用子类对象第三个语法机制是程序设计语言要支持方法的重写override。
在 Java 程序设计语言中对象变量是多态的。一个父类的对象变量既可以引用一个父类的对象也可以引用一个子类的对象。 一个 Employee 变量既可以引用一个 Employee 类的对象也可以引用一个 Employee 类的任何一个子类的对象例如 Manager、Executive、 Secretary 等。 对于多态特性的实现方式除了利用 “继承加方法重写” 这种实现方式之外还有其他两种比较常见的的实现方式一种是利用接口类语法另一种是利用 duck-typing 语法。不过并不是每种程序设计语言都支持接口类或者 duck-typing 这两种语法机制比如 C 就不支持接口类语法而 duck-typing 只有一些动态语言才支持比如 Python、JavaScript 等。
接口类语法一个对象变量接口类可以指向多种实际类型实现类duck-typing 语法duck-typing 可以这样表述“如果看起来像鸭子叫起来像鸭子那么它一定是鸭子”。 多态存在的意义、多态的好处
多态的好处是我们可以在一个比较稳定的、抽象的层面上编程而不被更加具体的、易变的实现细节干扰。多态也是很多设计模式、设计原则、编程技巧的代码实现基础比如策略模式、基于接口而非实现编程、依赖倒置原则、里式替换原则、利用多态去掉冗长的 if-else 语句等。
参考资料
《Java核心技术卷一基础知识》第10版
04 | 理论一当谈论面向对象的时候我们到底在谈论什么-极客时间 (geekbang.org)
05 | 理论二封装、抽象、继承、多态分别可以解决哪些编程问题 (geekbang.org)