2019-08-02 09:28:50 linxi8693 阅读数 58
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    3998 人正在学习 去看看 朱有鹏

00、前提概要

        记录在面向对象的实现方式,做参考未做详细实现细节

01、定义i2c类

typedef struct _class_i2c {
    GPIO_TypeDef * gpiox;
    GPIO_Pin_TypeDef sda,scl;
    void (*pf_start)(class_i2c *object_i2c);
    void (*pf_stop)(class_i2c *object_i2c);
    void (*pf_ack)(class_i2c *object_i2c);
    void (*pf_nack)(class_i2c *object_i2c);
    void (*pf_wait_ack)(class_i2c *object_i2c);
    unsigned char (*pf_readwrite)(class_i2c *object_i2c,unsigned char *buf);
} class_i2c;

02、实现所需函数

static void i2c_start(class_i2c *object_i2c){
}

static void i2c_stop(class_i2c *object_i2c){
}
class_i2c i2c;
i2c.gpiox = GPIOB
i2c.scl = GPIO_Pin_8;
i2c.sda = GPIO_Pin_9;
i2c.pf_start = i2c_start;
i2c.pf_stop = i2c_stop;
i2c_config(&i2c);
i2c_init(&i2c);

 

2017-01-06 23:54:19 black_yu 阅读数 3064
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    3998 人正在学习 去看看 朱有鹏

1.在看别人单片机程序时,你也许是奔溃的,因为全局变量满天飞,不知道哪个在哪用了,哪个表示什么,而且编写极其不规范。
2.在自己写单片机程序时,也许你也是奔溃的,总感觉重新开启一个项目,之前的写过相似的代码也无法使用,得重新敲,代码重用度不高。编程效率低下。代码无法积累。
3.而且感觉写这个代码没有思想,没有灵魂,没有框架,只是一个一个功能代码的堆砌,很空泛。

那么这个时候,我就想在单片机中引入面向对象的思想,使代码更规范。

引入面向对象的思想有两种方式:

1.直接使用C++编程,但是不好的是,效率有所降低,有些单片机编译器不支持。

2.通过C语言引伸出一种写法:

2.1类(class):

用来描述具有相同的属性和方法的对象的集合.
然而C语言中并没有类,但是我们可以跟java一样,通过文件来当做一个类,如有个类叫LCD,那我们就可以用LCD.c来表示有这么一个类,同时在文件中定义一个结构体:struct ScmLCD。

2.2那么面向对象有四个基本特性:

抽象,封装,继承,多态。
那么去其中比较有用的主要是封装,继承,多态。

2.3继承

其中,继承的话,可以使用文件的形式来表示,比如LCD.c这个类在LCD文件夹下,而LCD1602这个对象是LCD的子类,那么在LCD文件夹下还有一个文件夹叫LCD1602,而这个文件夹里有个文件叫LCD1602.c,然后在该文件里定义一个结构体struct ScmLCD1602。那么LCD1602属于LCD的一个型号,所以LCD1602就是继承于LCD.

2.4封装

然后是封装的话,封装主要通过一个结构体来封装“成员变量”,当然,安全性还是没有那么高,但是至少可以降低全局变量的滥用,提高可读性,如stLCD这个类有特征边变量:型号,显示的颜色,点数等  动作方法有:显示字符,显示数字等。然后定义几个指针变量void (*get_xxx)()获取特征,通过void (*set_xxx)(char *)来设置特征。
对于安全性的进一步提高,可以使用static,如静态全局,变量和静态修饰的函数,只能在该文件中调用。

2.5多态

接下来就是多态了,多态的话,比如说,LCD类有一个  void LCD_ShowChar(char *)的方法,那么LCD的结构体里定义一个结构体指针 void(*LCD_ShowChar)(char *),那么继承类LCD1602只要在.c文件里写一个                   void LCD1602_Showchar(char *)的方法,并在里面写上具体的实现。然后当要调用该类的这个现实方法时,则:

struct ScmLCD stLCD;
stLCD.LCD_ShowChar= LCD1602_Showchar;
那么接下来调用stLCD.LCD_ShowChar(“……”);就是调用LCD1602的方法。而如果今天换了一个型号的显示屏甚至主控芯片,那么这个时候则不需要重新编写实现代码,只要在文件夹LCD下增加如LCD12864文件夹,然后增加.c及结构体和实现方法,然后在开头修改stLCD.LCD_ShowChar= LCD12854_Showchar;那么接下来的就是调用LCD12864的方法,其他代码不变,哪天又换回来了,那么再改回stLCD.LCD_ShowChar= LCD1602_Showchar;即可。

补充:

单片机代码的需要大规模修改的原因有几个:

1.PCB布局的变化:

PCB布局变化主要是IO的变化,然后IO变化一般如果驱动程序是直接对IO操作的话就需要大规模改变代码,那么怎么提升代码的修改效率:可以在每个驱动子类里对IO进行define,那么只需要修改define代码,其他的不变的。

2.主控芯片的变化:

如果是主控芯片的变化,那么可能整个编译器或者说芯片内部资源的控制方式都发生变化,那么这个时候如果是按照上面的方法的话,驱动父类和功能类,及核心代码是不用变的,只要修改相应的驱动子类即可。

3.封装的变化:

那么封装发生变化,一般要修改IO和该封装的控制方式,即与之前的封装是有同一个父类,那么这个时候只需要添加相应的驱动即可,或者之前有已写好的,只要加入即可。

4.就是功能指标的变化:

功能指标的变化,那么一般分为子功能变化和核心功能变化,子功能只需要修改子功能类即可,核心功能修改的话,主要就是执行的顺序,那么这个需要引入队列和多任务机制,那么后续可以根据RTOS系统的一些写法来实现,这样的一个类来通用化

2019-06-11 11:30:21 Fancyyj 阅读数 165
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    3998 人正在学习 去看看 朱有鹏

面向对象的三大特性: 封装 , 继承 和多态

一. 面向过程编程
1.定义:
是一种以过程为中心的编程思想。这些都是以什么正在发生为目标进行编程,不同于面向对象的是谁在受影响。于面向对象明显 的不同就是封装,继承和类。
2.特点: 模块化 , 流程化
3.优点: 性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;单片机,嵌入式开发,Linux / Unix 等一般采用面向过程开发,性能是最重要的因素。
4 . 缺点: 没有面向对象易维护,易复用,易扩展。

二 . 函数式编程
1.定义: 函数 式编程是一种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要是λ演算。
2. 主要思想: 将运算过程尽量写成一系列嵌套的函数调用。

三. 面向对象的编程
(一)基础概念

  1. 定义:面向对象是按照人们客观世界的系统思维方式,采用基于对象(实体)的概念建立模型 ,模拟客观世界分析,设计,实现软件的办法。通过面向对象的理念使计算机软件系统能与现实世界中的系统的一一对应。

  2. 特性: 抽象 封装 继承 多态

  3. 优点: 易维护 , 易复位,易扩展,由于面向对象有封装,继承,多态性的特性,可以设计出低耦合的系统,使系统更加灵活,更加易于 维护

  4. 缺点: 性能比面向过程低。
    (二)对象和类

  5. 基本概念:
    类(Class)是现实或思维世界中的实体在计算中的反映,它将数据以及这些数据上的操作封装在一起。
    对象(Object ) 是具有类类型的变量。类和对象是面向对象编程技术中的最基本的概念。
    类和对象的关系: 类是一个泛指的概念,对象是一个具体的示例。

  6. 类的定义: class 类() : pass
    如何将类转换成对象:实例化是指在面向对象的编程中,把用类创建对象的过程称为实例化。是将一个抽象的概念类,具体到该类实物的过程。实例化过程中一般由 类名 对象名 = 类名 (参数1,参数2,…参数n)构成。

  7. 类是创建实例的模板
    对象是一个个具体的实例
    (三). 封装特性
    1.定义:将内容封装到某个地方,以后再去调用被封装在某处的内容
    所以在使用面向对象的封装特性时,需要:
    1)将内容封装到某处
    2) 从某处调用被封装的过程
    **(1) 通过对象直接调用被封装的内容:对象.属性名
    **(2)通过self间接调用被封装的内容:self.属性名
    **(3)通过self 间接调用被封装的内容:self.方法名()
    2.构造方法
    _ init_ 与其他的构造方法相比的不同之处在于,在一个对象被创建后,会立即调用构造方法。
    3.封装特性。
    对于面向对象的封装来说,其实就是使用构造方法将内容封装到对象中,然后通过对象直接或者self间接获取被封装的内容

eg. 创建一个类people 拥有属性姓名,年龄和性别。拥有的方法分别为购物,玩游戏和学习,实例化对象,执行相应的方法。
小明 18岁 , 男 , 去购物
小王 22岁 , 男, 玩游戏
小红 10岁 , 女 , 正在学习

代码如下:

class People:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

    def shopping(self):
        print("%s 正在购物" % (self.name))

    def playgame(self):
        print("%s 正在玩游戏" % (self.name))

    def learning(self):
        print("%s 正在学习" % (self.name))


xiaoming = People('小明', 18, '男')
print(xiaoming.name)
xiaoming.shopping()
xiaowang = People('小王', 22, '男')
print(xiaowang.name)
xiaowang.playgame()
xiaohong = People('小红', 10, '女')
print(xiaohong.name)
xiaohong.learning()

运行结果为:
在这里插入图片描述

(四) .继承特性

  1. 定义:继承描述的是事物之间的所属关系,当我们定义一个class的时候,可以从某个现有的class 继承,新的class称为子类,扩展类(subclass),而被继承的class称为基类,父类或者超类。
  2. 子类的继承方法:
    子类在继承的时候,在定义类的时候,小括号() 中为父类名字。
  3. 继承的工作机制:弗雷德属性方法会继承给子类。如果子类没有定义 _ init_ 方法,而父类有,那么在子类继承父类的时候这个方法就被继承,所以,只要创建对象,就默认执行了那个继承过来的 _ init_ 方法。
  4. 重写父类方法:在子类中,有一个和父类名字相同的方法,在子类的方法中会覆盖掉父类同名的方法
  5. 调用父类的方法:
    1)父类名.父类的方法名()
  1. super(): --在python2.2以上的版本能够使用
  1. 多继承
    1)多继承定义:子类有多个父类,并且具有他们的父类
    2)新式类和经典类
    在python2 及以前的版本中,由任意内置类型派生出的类,都是属于”新式类“
    反之,不由任意内置类型派生出的类,则称为 “经典类 ” 。

     新式类 :class  类名(object):
                          pass
     经典类:class  类名:
                           pass
    

    ( ps:新式类和经典类的区分在python3之后就没有了,在python3之后的版本中因为所有的类都派生自内置函数类型object(即使没有显示的继承object类型),所有的类都是“新式类”)

新式类和经典类的区别:
最明显的是多继承的搜索顺序不同
经典多继承搜索顺序(深度优先搜索),先深入继承树的左侧查找,然后再返回,开始在右侧查找。
新式类多继承搜索顺序(广度优先算法),先在水平方向查找,再向上查找
在这里插入图片描述

私有属和私有方法
私有属性: 只能在类的内部访问
私有方法: 外部无法调用的方法
表示方法:加 双下划线
优势: 确保了外部的代码不能随意修改对象内部的状态,这样通过访问限制的保护,使得代码更加健壮。
Q: 如果又要允许外部的代码修改属性怎么办?
A:可以给类增加专门设置属性的方法,
Q:为什么要这么麻烦,即设置为私有,又要允许外部修改?
A : 因为在方法中,可以对参数做检查,避免传入无效的参数。

(五) 多态特性

  1. 定义:多态,字面意思是 ”多种状态“ ,在面向对象语言中,接口的多种不同的实现方式即为多态。也就是说,同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。
  2. 多态的好处:
    当我们传入更多的子类,只要继承父类就可以了,而方法既可以直接不重写(使用父类的),也可以重写一个特有的,这就是多态。
    在调用的时候,只要调用就行,不用管原来的代码,这就是 “ 开闭 ” 原则。
    即 对扩展开放(Open for extension ):允许子类重写方法函数
    对修改封闭(Closed for modification ):不重写,直接继承父类方法函数

实例一:队列数据结构的封装
队列类。队列是具有先进先出特性的数据结构。一个队列就像是一行队伍,数据从前端被移除,从后端被加入。这个类必须支持以下几种方法。

在这里插入图片描述
并实现以下功能:
在这里插入图片描述
代码如下:

class Q(object):
    def __init__(self):
        self.queue = []

    def __len__(self):
        return len(self.queue)

    def enqueue(self, item):
        self.queue.append(item)
        print("%s 入队成功" % (item))

    def dequeue(self):
        if not len(self) == 0:
            item = self.Q.pop(0)
            print("%s 移除成功" % (item))
        else:
            raise Exception("队列为空")

    def  first(self):
        """获取栈顶元素"""
        if not self.is_empty() :
            # 获取出栈的元素
            item = self.queue[-1]
            print("队顶元素为: [%s] " % (item))
        else:
            raise Exception("队为空")

    def len(self):
        return len(self.queue)

    def is_empty(self):
        if len(self.queue) == 0 :
            print(True)
        else:
            print(False)
        return len(self.queue) == 0


queue = Q()
Q.enqueue(5)
Q.enqueue(3)
print(len(queue))
Q.dequeue()
Q.first()
Q.dequeue()
queue.is_empty()
print(len(queue))

实验结果如下:
在这里插入图片描述

示例二:最近请求次数(队列的应用)
写一个 RecentCounter 类来求最近的请求。
返回从3000毫秒到现在的ping数。
任何处于 [ t - 3000 , t ]时间范围之内的ping 都会被计算在内,包括当前 (指 t 时刻)的ping
保证每次对 ping 的调用都使用比之前更大的 t 值。

Python基础知识总结:

  1. 列举python2 和python3 的区别:
    A:1).print的表示:
    python2 中,print 后面不用写括号()
    python3中,使用时需要加括号()。
    2).在数值类型这方面
    Python2 有 long(长整型)
    python3 没有long (长整型)
    3)在数值类型这方面
    Python2 中: raw_input() 作用是 raw_input() 直接读取控制台的输入(任何类型的输入它都可以接收),而对于 input() ,它希望能够读取一个合法的 python 表达式,即你输入字符串的时候必须使用引号将它括起来,否则它会引发一个 SyntaxError 。
    python3 中 ,取消了raw_input() 所有的都用 input() 代替了
    4) Unicode
    Python2 中使用 ASCII 码作为默认编码方式导致 string 有两种类型 str 和 unicode
    Python3 对 Unicode 字符的原生支持,即Python3 只支持 unicode 的 string
    5)新式类和经典类
    python2 中,有新式类和经典类之分
    python3 中,统一采用新式类,新式类声明要求继承 object,必须用新式类应用多重继承

  2. 深拷贝与浅拷贝
    A:浅拷贝:浅拷贝是“引用”,指把存放变量的地址值传给被赋值,最后两个变量引用了同一份地址,当其中的一个变量被删除,或者被改变的时候,其他指向该地址的变量也不能再使用了。

深拷贝:深拷贝是拷贝值,指被赋值的变量开辟了另一块地址用来存放要赋值的变量的值(内容)。在改变
在 python中引用 copy 模块,浅拷贝是 copy.copy ,深拷贝是 copy.deepcopy

  1. *args 和 **kwargs *args 和 **kwargs 都是用在函数定义的时候 ,两个的共同点是都可以传入不定量个参数(可以是1个,2个…n个,或者没有参数)

A:*args 是可变参数, 用来接收多个变量或者参数,args 接收进来的是一个元组。

**kwargs 是关键字参数,是一个函数里处理带名字的参数用来接收多个变量或者参数, kwargs 接收进来的是一个字典。

  1. 简述 生成器 , 迭代器 , 可迭代对象 以及应用场景。
    A: (1)生成器:在python中,一边循环一边计算的机制,称为生成器。(Generator)。使用yield关键字
    (2)迭代器:迭代器是访问容器中元素的一种方式。迭代器是一个可以记住 遍 历位置的对象. 可以进行 next() 函数调用并不断返回下一个值的对象。(Iterator)
    (3)可迭代对象: 可以进行for() 循环的对象。(eg. list,set,str等)
    相互之间的关系为:
    1)生成器都是迭代器,但迭代器不一定是生成器。
    2) 迭代器都是可迭代对象,但可迭代对象不一定全是迭代器。可以用iter() 来将可迭代对象转换成迭代器。
    应用场景:
    生成器:因为是一边循环一边计算的机制。所以当要读取的文件大于内存时,一般会使用生成器,因为如果直接打开文件,会造成内存溢出的现象,而使用生成器的话,只需导入需要的部分即可。很大程度的节省空间。eg. 生产者消费者模型,斐波那契数列的实现。(具体见高级特性)

  2. yield 的工作机制
    A: yield时在生成器中使用的。带有yield 就是一个迭代器。yield就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后(下一行)开始。在调用函数时,遇到yield就停止,返回此时的迭代值,当下次调用next()的时候不是从头调用,而是从上一次yield 停止的地方继续开始。且
    只有遇到next() 方法时,才会调用。

  3. 装饰器的作用和功能。
    A: 装饰器的作用:装饰器可以在不改变原本已经写好的代码的同时,可以给该代码赋予新的作用 ,这也就是所谓的在写代码的时候要遵循“开放封闭“原则。封闭是对已经实现的功能代码块。开放是对扩展开放。
    装饰器的功能:
    1)引入日志
    2)函数执行时间统计
    3)执行函数后的清理功能
    4)执行函数前的预备处理
    5) 权限效验等场景
    6)缓存

  4. python 中如何读取大数据的文件内容?
    A: 1)通常来说,使用read 方法,可以读取整篇文章。
    对于大文件可以使用readline(),这个是每次读取文章的一行
    readlines() 是一次读取文章的多行。
    在文件特别大的时候若使用read() 方法会造成内存溢出的情况, 因此较为常见的是使用readline() , readlines() 方法
    2)使用 生成器。
    调用 next() 方法,遇到yield 就停止。这样可以读取想要的文件,而不用一次性读取所有的文件。从而造成内存溢出。
    3)使用 open() 方法
    open(“file.txt” ,a+)

  5. python中的模块和包是什么?
    A: 模块: 模块实际上就是一个工具包,如果想要使用这个工具包,就要导入这个模块。eg . 引用random 模块时: import random
    包: 包是将有联系的模块组织在 一起,有效的避免各个模块名称的冲突。当然,除了python已有的包之外,自己也可以定义的模块,并且将自己的模块打包,封装,之后就可以发给其他人,让其他人也可以使用你定义的包。

  6. python是如何进行内存管理的?(python是如何实现垃圾回收的?)
    A: python 所采用的垃圾回收机制:python采用的是引用计数机制为主,标记—清除和分代收集两种机制为辅的策略。
    (ps . 引用计数机制是指python内部记录了对有多少个引用,当这个对象的引用计数为0 时,垃圾处理机制就会将它按照垃圾处理掉
    标记清除就是将所有的活动对象都标记起来,然后清除那些没有被标记的对象。)

  7. 谈谈对面向对象的理解
    A: 面向对象就是按照客观世界人们的思维方式,采用基于对象(实体)的概念建立模型 ,模拟客观世界分析,设计,实现软件的办法。使得计算机的系统体系和人类的思考问题方式相同。
    通过对代码的编写,达到人们所预计的结果的方式就是面向对象的编程。

  8. python面向对象的继承有什么特点?
    A: 1)继承就是父类里面一些已有的特性,或者功能,在子类中不用再次定义,直接继承就可以了,这样可以避免重复减少代码量使代码更加简洁 。
    2)子类在继承父类的构造(init()方法)会被自动调用,而没有继承的则需要 专门的调用才可以使用。
    3)在调用父类需要加上父类的类名前缀,且要加上self参数变量。
    子类在继承父类的过程中,如遇与父类定义不同的方法时,定义与父类相同名字的方法,在子类中会覆盖掉父类同名的方法

  9. 面向对象中的super 有什么作用?
    A:这是子类调用父类的一种方法。

  10. 面向对象深度优先和广度优先是什么,并说明应用场景。
    A : 深度优先搜索在面向对象中是经典多继承搜索顺序,先深入继承树的左侧查找,然后再返回,开始在右侧查找。
    广度优先算法在面向对象中是新式类多继承搜索顺序,先在水平方向查找,再向上查找。
    应用场景:在python3中全部都是新式类多继承顺序。主要应用于多继承的时候并且要写(object)

  11. 请简述 _init _ 和 _len _ 这两个魔术方法的作用
    A: _init _ 是在类实例创建的时候自动会执行的。_init _ 的第一个参数是self,表示创建实例的本身, 之后可以加其他的参数。类其实可以相当于一个模板,里面添加的参数在实例创建的时候自动执行(: 有了 _init _ 方法之后不能空的参数,必须传入与 _init _ 方法相匹配的参数,self 不用传入,解释器会自动将实例变量传入进去)
    _len _ 方法:在类的定义 _len _ 方法是用来测量传入参数的长度的,比如说先定义一个空列表,然后向列表中传入值,之后测量列表的长度,或者判断列表是否为空。这个也是为了让len() 函数正常运行,类所要提供的一个特殊的方法len(),来返回元素的个数。

2018-10-04 22:16:47 m0_37697335 阅读数 434
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    3998 人正在学习 去看看 朱有鹏

《单片机编程魔法师之高级裸编程思想》以单片机裸环境为基础,为编程者定义了一个微操作系统(MOS)的编程环境,并面向应用中不断提高的需求对编程策略进行了深度剖析与研究,从而分离出数据驱动、并行多任务、面向对象等重要编程思想。这些思想既可独立运用,又可有机结合成一个体系,是我们实践中解决问题的致胜法宝。《单片机编程魔法师之高级裸编程思想》以实例为基础,分6章对这一思想体系进行了阐述。阐述通常以提出问题开始,然后针对解决问题的现状,从心理学的角度对问题展开讨论,力求将容易遇见的问题一网打尽。《单片机编程魔法师之高级裸编程思想》通过一些列的优化过程对思想要点进行完整描述,然后通过软件仿真手段给读者一个清晰的认识,并在最后进行归纳总结。

《单片机编程魔法师之高级裸编程思想》既介绍了思想,又介绍了使用思想的方法。无论您是单片机自动化领域的初行者,还是资深的单片机自动化领域的工程师,《单片机编程魔法师之高级裸编程思想》都将成为您的得力帮手。希望这种既有理论又有方法论的阐述方式能帮助读者在事业上更上一层楼。

该书PDF格式的链接:链接:https://pan.baidu.com/s/1WIyZvfq__jCOaZU_B4Mz1w   提取码:mldv

下面是我的一些体会和总结:

(一)数据驱动程序思想描述文章链接:数据驱动程序

 

 

2015-04-10 10:36:28 u012942818 阅读数 5232
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    3998 人正在学习 去看看 朱有鹏
面向对象和面向过程的区别,实在是难用一两句话说明白。
 
面向过程是一种直接的编程方法,它是按照编程语言的思路考虑问题。尤其是想C语言这种过程式语言,它就是通过顺序执行一组语句来实现一个功能,这些语句的执行过程就是整个程序。不同的语言解决同一个问题的过程是不一样的。
 
面向对象是一种抽象度更高的编程方法。它把眼光集中在了要解决问题本身而不是语言上。它的目标是使模块的抽象度更高,可复用性更好。面向对象的目的就是可复用。
 
举个例子,比如我们要写一个计算器程序。这个计算机目前只要求有加减乘除四种运算。
 
用面向过程的方法,我们可能直接就写一个main函数。然后就开始定义一些数据结构,然后就开始写add,sub,multi,div等函数,去实现功能。
 
用面向对象的方法,我们会先定义一个Calculator类。然后定义一些必要的数据成员,然后在定义add,sub,multi,div这四个成员函数(这四个函数的功能实现和上面四个应该是基本一样的)。
 
从上面的实现来看,这两种实现方法的差别不是很大,甚至第二种看上去还有些多此一举。
 
接下来,我们要扩展这个计算器,让它能计算指数。
 
用面向过程的方法,我们会将上面实现的代码全部copy过来,然后再增加一个power函数。
用面向对象的方法,我们会定义一个CalculatorEx类公有继承自Calculator,再在CalculatorEx中实现Power函数。
 
上面只是一个简单的扩展,二者的区别就明显起来。面向过程是纯代码级的复用。面向对象的复用方式更为优雅,它可以是代码级的,也可以是类级的,也可以是接口级的,也可以是组件级的,甚至是服务级的。抛下这些复用概念不说。我们假设第一次实现的并不是简单的四个功能,而是一个复杂的库,第二次增加的也不是一个功能而是一个扩展库。这时候面向对象的优势就会比较明显的体现出来。面向过程是松散部件,而面向对象是一个体系。
 
我说的这些都是自己的理解,可能并不完全正确。对于面向对象有一个官方的定义,但是不同人有不同的理解。所以里面的很多东西都需要在学习的过程中去理解体会。但是,如果不动手做点东西,对这些概念很难理解到位。
 
还有就是,C,C++,Java这些都是语言,他们之间并没有是不是面向对象的区别。用C同样可以写面向对象的程序,看看Linux的内核代码就知道了。C++,Java一样可以写面向过程的程序,他们之所以叫面向对象的编程语言是因为他们提供的语言特性更易于实现面向对象的编程方法,并不是说他们只能做面向对象编程。
 
还有就是并不是说面向对象一定优于面向过程。在很多领域是无法实施面向对象的方法,如硬件编程和嵌入式编程这种实时性和效率要求高的领域就无法用到面向对象。面向对象的主要领域还是用在大型,复杂型的软件系统中。
没有更多推荐了,返回首页