面向对象是如何工作的(How Objects Work)

How Objects Work - 面向对象是如何工作的

面向对象的全貌和概念

  1. 面向对象是从编程语言进化为编程技术的

    1. 1967 年挪威设计的 Simula 67 编程语言首次提出

    2. 艾伦 凯设计的 Smalltalk 沿用此架构,开创“面向对象”的概念

        * The best way to predict future is to invent it - Alan Kay
  2. 面向对象三大混乱之源

    1. 术语洪流

    2. 比喻乱用

    3. “一切都是对象”综合征

  3. 面向对象三大要素

    1. 类(封装)Encapsulation | class -> instance

    2. 多态 Polymorphism

    3. 继承 Inheritance

  4. 集合论和职责分配

    1. 集合论:在 OOP 中,类用于汇总子程序和变量。实例是基于类定义在运行时分配的内存区域

    2. 消息传递:在 OOP 中,消息传递是一种通过指定实例来调用类中汇总的子程序(方法)的结构

编程技术

  1. OOP的出现的必然性之语言历史 - 计算机只可以解释用二进制编写的机器语言

    1. 机器语言

    2. 汇编语言:An assembly language is a low-level programming language designed for a specific type of processor

    3. 高级语言:

  2. 重视易懂性的结构化编程

    1. 荷兰科技加戴克斯特拉(Dijkstar):为了编写能够正确运行的程序,采用简单易懂的结构是非常重要的

        1. 循序->顺序执行->从头开始顺序执行程序中编写的命令
        2. 选择->执行某些判断,根据判断的结果决定接下来要执行的命令
        3. 重复(循环)-> 在规定次数或某个条件成立期间,重复执行指定的命令群
  3. 提高子程序的独立性,强化可维护性

    1. 多个子程序之间共享的变量叫全局变量

    2. 减少全局变量对提高程序整体可维护性而言非常重要

    3. 避免全局变量引用造成的混乱,创造

        1. 局部变量:只可以在子程序中使用的变量,在进入子程序时创建,退出子程序时消失
        2. 按值传递(Call By Value):通过参数向子程序传递消息时,不直接使用调用端引用的变量,而是复制值以进行传递。
  4. 结构化语言的缺陷

    1. 全局变量问题:在子程序运行结束后依然需要保持的信息只能存放在子程序外面,即被保存为全局变量

    2. 可重用性差

  5. OOP(Object Oriented Programming) - 编程架构

    1. OOP 的出现解决结构化编程两个主要问题:

        1. OOP 具有不使用全局变量的结构
        2. OOP 具有除公用子程序之外的可重新结构
    2. OOP 的类(Class)结构将紧密关联的子程序(函数)和全局变量汇总在一起,创建大粒度的软件构件

    3. 多态和继承能够将公用子程序无法很好地处理重复代码进行整合

    4. Class 类的功能是汇总、隐藏和“创建很多个”

        1. 汇总子程序和变量 -> 构件的数量会减少、函数的命名变的轻松、函数容易查找
        2. 隐藏只在类内部使用的变量和子程序 -> 能对其他类隐藏类中的定义的变量和方法
        3. 从一个类“创建很多个”实例 -> 指定实例,调用方法
            * 实例是指类定义的实例变量所持有的内存区域
    5. 实例变量时存在期间长的局部变量或限定访问范围的全局变量

        1. 能够隐藏,让其他类方法无法访问
        2. 实例在被创建后一直保存在内存中,直至不再需要
    6. Ploymorphis 多态创建“公用主程序”的结构

        1. 多态是统一调用子程序端的逻辑的结构,即创建公用主程序的结构
        2. 统一调用端的逻辑
    7. Inherited 继承去除类的重复定义的继承

        1. 继承就是"将类的共同部分汇总到其他类中的结构”
        2. 继承是将类定义的共同部分汇总到另一个类文件中,并除去重复代码的结构
    8. 类型检查

        1. 通过嵌入类型使工作变的轻松,指定的类型的原因:
            1. 告诉编译器内存空间的大小
            2. 防止程序发生错误
        2. OOP 中将类当作类型使用
            1. 将变量的类型指为类、将方法的参数类型指为类、将方法的返回值类型指定为类
            2. 类型检查分为强类型和弱类型 -> 强类型:在编译时进行检查 / 弱类型:在运行时进行检查
    9. OOP 进化

        1. 包 -> Package  1. 用户创建层次结构 / 2. 用于防止类重命名
        2. 异常 -> Exception
        3. 垃圾回收 -> Grabage Collection GC
  6. 程序的内存结构

    1. 程序的内存区域分为 静态区、堆区、栈区

        1. 静态区:从程序开始运行时产生,在程序结束前一直存在。所谓"静态"该区域中存储的信息配置在程序运行时不会发生变化
        2. 堆区(heap): 程序运行时分配的内存储区域,程序开始运行时预先分配的大量内存区域,供多个线程使用
        3. 栈区(Stack):由线程控制的内存区域。仅每个线程自身使用.
            * 各个线程依次调用子程序(OOP中的方法)。即子程序的内存区域,存储子程序的参数、局部变量和返回位置等信息
            * LIFO(Last In First Out)
    2. 每个类只加载一个类信息

        1. 当使用 OOP 编写的程序运行时,会从类创建实例进行动作。实际上,当程序运行时,在创建实例之前,需要将对应的类信息加载到内存中
            * 类信息,是不依赖于各个实例的类固有信息
        2. 每个类只加载一个方法中编写的代码信息
        3. 加载信息的时间点:
            1. 预先整体加载所有类信息
            2. 需要时依次将类信息加载到内存中
    3. 每次创建实例都会使用堆区(Heap)

        1. 执行创建实例的命令,程序会在堆区分配所需的大小内存,用于存储该类的实例变量
        2. OOP 中的内存使用方法最大特征就是实例的创建方法
        3. 使用 OOP 编写的程序大量使用有限的堆区来运行
        4. 传统编程语言编写中,将代码和全局变量配置在静态区,并使用栈区传递子程序的调用信息
    4. 在变量中存储实例的指针

        1. 指针表示内存区域中的位置的信息
        2. 存储实例的变量存储的并不是实例的本身,而是实例的指针
        3. 复制存储实例的变量需要多
      

应用技术

  1. 软件建模

    1. 业务分析:直接把我现实世界的情形

    2. 需求定义:考虑计算机的性质,确定计算机承担的工作范围

        * 计算机擅长固定工作和记忆工作
    3. 设计:考虑硬件性能、操作系统和中间件的特性以及编程语言的表现能力等,确定软件结构

  2. 软件建模示例

    1. 活动图表示工作流程

    2. 用例图表示业务

    3. 概念模型表示系统信息

  3. 面对对象的设计的目标(可维护与可重用)

    1. 去除重复 (多态、继承)

    2. 提高构件的独立性 (高内聚、低耦合)

        1. 内聚度:评判软件构件所提供功能互相结合紧密程度的标准,结合越紧密,内聚度越高,设计就越好
        2. 耦合度:多个软件构件之间互相依赖的标准,依赖程度越低,耦合程度越低,设计越好
    3. 避免依赖关系发生循环

    4. 面向对象的设计“感觉”拟人化和职责分配

    5. 关联 -> 依赖 -> 继承(三角)-> 实现(三角)

  4. 函数式语言特征

    1. 使用函数来编写程序 - 函数应用

    2. 所有的表达式都有返回值 - 命令式语言、表达式、表达式求值、lambda 表达式

    3. 将函数作为值进行处理 - 头等函数、高阶函数

    4. 可以灵活组合函数和参数 - 部分应用、柯里化、函数组合

    5. 没有副作用 - 副作用、绑定、引用透明性、延迟求值

    6. 使用分类和递归编写循环处理 - 模式匹配、递归

    7. 编译器自动进行类型推断 - 类型推断、多态、多态类型、类型变量

标签: none

添加新评论