vlambda博客
学习文章列表

编程范式:范型编程、函数式编程、面向对象

编程范式

每个编程语言,都是在特定的环境下为解决特定的问题而产生的。

泛型编程

泛型编程的思想是将不同的数据类型结合在一起。

首先来看这么一个 C 函数:

void swap(int* x, int* y) {
 int tmp = *x;
 *x = *y;
 *y = temp;
}

swap 函数通过指针来实现了两个 int 型变量的交换,但是该函数有一个问题:如果实现任何数据类型的变量的交换?

对此,需要有一种泛型的概念:对于传入的所有类型,我的函数均可以正确处理。

那么,在 C 语言中,可以这么写:

/**
 * 交换两个参数
 * @param x 需要交换的参数
 * @param y 需要交换的参数
 * @param size 指定 x 和 y 类型在内存中的大小
 * */
 
void swap(void* x, void* y, size_t size) {
 // tmp 是用于数据交换的临时空间存储
 char tmp[size];
 // 存储 y
 memcpy(tmp, y, size);
 // 交换 x, y
 memcpy(y, x, size);
 memcpy(x, tmp, size);
}

在 Cpp 中,使用模板来定义函数和类型,进而实现了范型编程:

template<class T>
void swap(T* a, T* b) 
{
 T temp = *a;
 *a = *b;
 *b = temp;
}

如果有一些 python 基础,可以通过执行下列代码实现 swap:

a, b = b, a

函数式编程

函数式编程只关心输入数据和输出数据的关系。

函数式编程具有以下特性(下面示例代码均为 JavaScript)

  • 函数是一等公民:函数与其他数据类型一样,可以当作变量赋值,也可以当作参数,也可以当作返回值。

    // 函数当作变量赋值
    let sum = (a,b) => a + b;
    function a(f{
      // 函数被当作参数传入
      f()
      // 函数被当作参数返回
      return f;
    }
  • 无副作用:不修改变量。

    // 无副作用函数
    let sum = (a,b) => a + b;
    // 有副作用函数
    let addOne = (a) => {
      a += 1;
      return a;
    }

因为上述原因,也导致函数式编程可能会对性能有一些影响,例如 sum 中,返回结果为 a + b, 为重新生成了一个变量;但是在 addOne 中,只是对原有变量操作。

面向对象编程

面向对象具有三大特性:封装、继承、多态。

以 Java 代码作为示例,来看什么是面向对象:

/**
 * 封装的 Animal 类型
 */

public class Animal {
    String type = "animal";
    String name;

    public Animal() {
        this.name = "undefined name";
    }

    /**
     * 构造函数的多态
     */

    public Animal(String name) {
        this.name = name;
    }

    public void bark() {
        System.out.println(this.name + "is barking");
    }
}

class Dog extends Animal {
    String type = "Dog";

    /**
     * 重载
     */

    @Override
    public void bark() {
        // 覆盖
        System.out.println("dog bark");
    }
}