什么是编程范式
编程范式(Programming parading),即编程的模式、方法,指编程风格。
编程范式是编程语言的一种分类,并不针对某种编程语言。
一种编程语言可以适用多种编程范式
一些编程语言是为某种特定的编程范式设计的:
- C语言是过程式编程(面向过程编程)语言
- Java、Smalltalk是较纯粹的面向对象编程语言
- Haskell是纯粹的函数式编程语言
一些编程语言与编程范式没有固定的一一对应关系:
- Python,Scala,Groovy支持面向对象编程及一定程度的函数式编程
- C++是多范式编程语言,它是面向过程编程语言,同时支持面向对象编程,STL使C++具有了泛型编程能力
- Swifthi多范式编程语言,支持面向对象编程,函数式编程,范型编程
常见编程范式
不同编程语言偏爱不同的编程范式:
- 面向过程编程(命令式编程)
- 面向对象编程
- 函数式编程
- 范型编程
不论用哪种编码方式,都是为了写出更通用,可复用,更具有重用性的代码或模块。
面向过程编程(命令式编程)
也称为‘命令式编程’,是一种最原始,日常工作中使用较多的一种编程范式。
面向过程的核心即将问题分解,将解决步骤分析出来,然后按步骤一步一步解决问题。
面向过程编程是一种直观的编程方式,更符合我们日常的思维方式。
用于计算机语言中,面向过程编程,更关注计算机的执行步骤,即一步步告诉计算机应该做什么。
优缺点
优点
- 面向过程编程,思维方式简单,利用程序流程图能够清晰的完成编码思路
- 面向过程编程,适合解决线性问题,强调自上而下、精益请求的设计方式
- 底层灵活且高效,适合开发运行较快、系统资源利用率要求较高的程序
缺点
- 不适合解决某些种类问题。(如:非结构的具有复杂算的问题)
- 当项目庞大、逻辑复杂时,会面临命名冲突、代码重复冗余的问题,不利于代码的可读性及可维护性。
流程驱动编程
主动轮询,行为取决于自身的判断,是流程驱动的
事件驱动编程
被动等通知,行为取决于外界事件,是事件驱动的
面向对象编程
面向对象编程(Object-oriented programming,简称OOP),是通过类、方法、对象、消息传递来支持面向对象的编程范式。
(消息传递:一个对象调用了另一个对象的方法)
(对象指类的实例)
将数据和方法封装在对象中,对象中的方法可以访问及修改对象中的数据,提高代码的复用性、灵活性、可拓展性。
面向对象编程的特性
封装
封装为两个过程:
将数据和操作(方法)捆绑在一起,创造出一个新的类型的过程。
将接口与实现分离的过程。
通过封装,使软件结构相关部件实现“高内聚,低耦合”,这是封装性所需要的基本目标。
对用户来说,不需要了解程序的内部实现细节,只需要通过接口调用程序。
继承
一个类共享了一个或多个其他类定义的方法和属性。
子类可以对基类的行为(方法)进行扩展、覆盖、重定义,子类会比基类更为具体化。
多态
由于继承产生的多个相关但不同的类。
多个类在接收到完全相同的消息时,会产生不同的响应。
名词解释
类:相似对象的集合,定义了一件事物的抽象特点。
动态绑定:也称动态类型,指一个对象或者表达式的类型在运行时才确定。通常由编译器插入特殊代码实现。
静态绑定:也称静态类型,指一个对象或者表达式的类型在编译时确定。
消息传递:一个对象调用了另一个对象的方法。
方法:也称成员函数,指对象上的操作。方法定义了可以对对象执行的操作。
优缺点
优点
- 数据抽象概念可以在保持外部接口不变的情况下,改变内部实现,从而减少对外部的干扰。
- 通过继承机制,可以减少冗余代码,方便拓展现有代码。提高编程效率,降低代码维护成本。
缺点
- 运行效率低:类的大量加载会牺牲系统性能,降低运行效率。
- 类库庞大:由于类库庞大,需要一定学习成本。
- 类库可靠性:无法保证类库中每个类在各个环境中百分百正确。
函数式编程
函数式编程(Function programming,简称FP),又称函数式程序设计、泛函编程。
函数式编程将计算机运算视为函数运算,并且避免使用程序状态以及易变对象。
λ演算(lambda calculus)是函数式编程最重要的基础。λ演算的函数可以接受函数作为输入和输出。
函数式编程关心类型之间的关系,即输入类型和输出类型之间的关系。
λ演算就是给λ表达式一个输入类型的值,得到一个输出类型的值。
函数式编程更加强调程序的执行结果,而非执行过程。倡导利用简单的执行单元,逐层推导复杂的运算,而非设计一个复杂的执行过程。
函数式编程时面向数学的抽象,将计算描述为一种表达式求值,函数式程序就是一个表达式。
在函数式编程中,函数可以出现在任何位置。可以把函数作为参数传递给另外一个函数,函数也可以作为另外一个函数的返回值。
函数式编程的本质
函数式编程中的函数并非计算机中的函数,而是指数学中的函数,是指一种映射。函数的输出值取决于函数的输入值,不依赖于其他状态。
在函数式语言中,函数作为一等公民,可以在任何地方定义、使用。
函数式编程中的变量并非编程语言中的变量。
编程语言中的变量指存储单元。
函数式编程中的变量指值的名称。
函数式语言的条件语句、循环语句也不是命令式编程语言中的控制语句,而是函数的语法糖。
函数式编程意味着,不使用可变的变量、赋值、循环和其他命令式控制结构进行编程。
理论上,函数式语言不是通过冯·诺依曼体系结构的机器运行的,而是通过λ演算来运行。
但是大多数情况下,函数式程序还是被编译成机器语言执行指令。
函数式编程的特性
函数是一等公民(First-class Function)
函数优先,函数可以在任何地方定义、使用。
只使用表达式
通过表达式计算过程得到返回值,而非通过语句修改状态
无副作用
不污染变量,相同输入永远得到相同输出
不可变性
变量值不可变。
对值的操作并不是修改原来的值,而是产生新的值,原来的值保持不变。
纯函数编程语言无法实现循环。
For循环使用可变状态作为计数器。
While循环使用可变状态作为循环及跳出循环条件。
函数式编程使用递归解决迭代问题,故函数式编程严重依赖递归
高阶函数(Higher-order function)
即参数为函数或返回值为函数的函数。—-将复用的粒度降低到函数级别。
偏应用函数(Partially Applied Functions)
一个函数接收一个有多个参数的函数,返回一个需要较少参数的函数。
偏函数将一到多个参数在内部固定,然后返回新函数,返回的函数接收剩下的参数完成函数的应用
柯里化(Currying)
输入一个有多个参数的函数,返回一个只接受一个参数的函数
闭包(Closure)
引用了自由变量(不属于当前函数作用域的变量)的函数。
特性:
闭包是定义在函数中的函数
- 闭包能访问外部函数中的变量
- 外部函数执行完毕后,被闭包引用的变量不会被释放。
优缺点
优点
引用透明,没有副作用
因为函数式编程变量的不可变性
不易出错,易于单元测试及调试
因为函数式编程的无副作用,不影响外部环境,不依赖外部环境,相同输入永远有相同输出。
更好的处理并发
多个线程不共享状态,不争夺资源,不需要锁保护可变状态,不会出现死锁。
无this指向问题
惰性求值,提升性能
将表达式赋值给变量时不做计算,变量第一次被使用时才做计算。避免不必要的求值,提升性能。
模式匹配
可以定义代数数据类型,通过组合已有数据类型形成新的数据类型。代数数据类型的值可以通过模式匹配进行分析。