wika 威卡 wika压力表 威卡压力表 wika双金属温度计 威卡双金属温度计 wika压力表 wika压力变送器 wika温度计 威卡压力变送器 威卡温度计 wika 威卡 wika压力表 威卡压力表 wika双金属温度计 威卡双金属温度计 wika压力表 wika压力变送器 wika温度计 威卡压力变送器 威卡温度计 wika 威卡 wika压力表 威卡压力表 wika双金属温度计 威卡双金属温度计 wika压力表 wika压力变送器 wika温度计 威卡压力变送器 威卡温度计 wika 威卡 wika压力表 威卡压力表 wika双金属温度计 威卡双金属温度计 wika压力表 wika压力变送器 wika温度计 威卡压力变送器 威卡温度计 宝宝八字取名字| 古代风水学大师| 鞋店起名网免费取名| 射手座男和水瓶座女| 中国风水网| 紫微斗数旺夫| 属猪的人今年多大| 赣州杨公风水| 公司免费取名大全| 属牛的宝宝取名| 曲炜风水培训| zippo十二星座| 天蝎座2012年运势| life算命| 水瓶星座配对| 墓穴风水| 杨森批八字| 属鸡人的运程| 风水梁| 贸易公司取名| 属鼠的今年多大2014| 风水师工具| 易久堂十二生肖运程| 双子座男生巨蟹座女生| 八字基础| 属鸡的几月出生最好| 风水学的古称是什么| 取名字吧| 房子的风水| 投资公司怎么取名字| 射手座男星| 办公室风水师| 手相川字掌| 2015兔人运程| 房子装修风水| 夫妻算命生辰八字| 今天的黄道吉日| 极品风水师txt下载| 给牛宝宝取名| 学风水| 五行术士| 横财运| 2015年蛇年运程| 风水葫芦| 周公解梦梦见剪头发好吗| 属兔的2013年运程| 买房子怎么看风水| 生物工程公司起名| 名人风水| 周公解梦梦见小男孩| 手掌的财运线| 属相星座配对测试| 赖布衣风水| 周公解梦梦见小狗| 属虎和什么属相不合| 韩剧大风水| 房地产企业起名字| 家居装修风水| 摇钱算卦| 出生年月婚配| 风水吧| 小孩八字免费起名| 巨蟹座女生的运气| 14画五行属土的字| 墓地风水学| 办公室风水禁忌| 香港风水| 方姓女孩取名| 属猪女和属牛男| 2345算命网址大全| 14

设计一个处理工资单数据包,继承与多态不可忽略!

周立功单片机 ? 2018-07-18 10:18 ? 次阅读
>>> 1.1.1 抽象
标签:詹妮弗 11 李居明2012属马运程

假设需要设计一个处理工资单的数据包,可以将排序作为一个关键的业务进行抽象。虽然各种排序的实现不一样,但它们的共性都是“排序”,这就是抽象的基础。如果要建立一个矩阵代数程序包,就要讨论抽象矩阵。虽然各种类型矩阵的实现各不相同,但根据它们表现的共同行为特性,可以将这些矩阵归为一类,显然其共性又一次支持了抽象。

如果用户有一个这样的需求——校验push到栈中的数据,则实现者一定会问“校验规则是什么?”因为校验是一个非常“抽象”的概念;如果用户明确地告诉实现者——对push到栈中的数据进行范围值校验或偶校验,则不会出现这样模糊的问题。当需要对push到栈中的数据进行范围值校验时,则需要编写一个RangeValidator类;当再需要添加一个奇偶校验器时,势必又要编写一个OddEvenValidator类。显然每添加一种校验器就要增加一个接口,根本无法做到重用。

虽然它们的类型不同,且不同校验器的对象各有不同,但它们共同的概念都是“校验器”。回归校验器的本质,无论是什么校验器,其共同的属性是校验参数,其共同的行为是可以使用相同的方法——在动态中根据对象的类型调用不同的校验器函数。

显然,用户是在概念层次上提出了校验的需求与实现者交流,而具体如何校验是在实现层次进行的,用户无需准确地知道具体是如何实现的。因此只要概念不变,即可做到用户与实现细节的变化完全分离。

在面向过程编程中,新手对共性的认识往往来源于直觉,以创建范围值校验器类和偶校验器类为例,程序员普遍都会按照以下方法表达这种共性,将Validate提取为一个公共的函数指针。比如:

1    typedef bool(*const Validate)(void *pThis, int value);

2    typedef struct{ 

3          Validate validate;

4          const int min;  

5          const int max; 

6    }RangeValidator;

7

8    typedef struct{

9          Validate validate;

10        bool isEven; 

11  }OddEvenValidator;

而对于一个拥有“面向对象思维”且经验丰富的程序员,更倾向于将各种校验器的共性打包在一个函数指针中作为结构体的成员创建一个抽象类。Validator抽象类的定义如下

1    typedef struct _Validator{ 

2          bool (*const validate)(struct _Validator *pThis, int value); 

3    }Validator;

其中,pThis是指向当前对象的指针,Validator是一个没有具体属性,代表多种具有共性的数据和行为的具体校验器总称的抽象类。Validator类没有提供任何实现validate方法的代码,正是因为这一点,该方法才能成为一个抽象的方法,因为提供任何代码都会使方法成为具体方法。

由于Validator是一个抽象类,因此无法创建实例,自然也就不知道要校验什么?那么谁知道呢?范围值校验器和奇偶校验器类知道自己要做什么校验。由于Validator有一个validate方法因此可以将Validator抽象类封装成RangeValidator派生类的成员——Validator类的变量isa,即将实现细节委托给子类。范围值校验器和奇偶校验器类重新定义,各自实现它自己的validate方法。

>>> 1.1.2 继承

在这里将引入一个新的概念继承描述类之间的关系。由于RangeValidator范围值校验器OddEvenValidator奇偶校验器的共性是校验参数和调用校验函数的方法因此将其共性上移到一个名为Validator校验器类(父类)中

基于此将具有可变性的校验参数分别转移到RangeValidator和OddEvenValidator中的同时,并将Validator类型的变量isa作为结构体的成员,即可创建新的结构体数据类型

1    typedef struct _Validator{ 

2          bool (*const validate)(struct _Validator *pThis, int value); 

3    }Validator; 

4    Validator *pThis; 

5

6    typedef struct{ 

7          Validator isa;                                     // 继承自Validator类

8          const int min; 

9          const int max; 

10  } RangeValidator; 

11  RangeValidator rangeValidator;

12

13  typedef struct{ 

14        Validator isa;                                     // 继承自Validator类

15        bool isEven;

16  } OddEvenValidator; 

17  OddEvenValidator oddEvenValidator; 

其中,pThis为指向Validator类对象的指针,RangeValidator和OddEvenValidator派生自Validator类,RangeValidator和OddEvenValidator是Validator的子类,Validator类是RangeValidator和OddEvenValidatorr类的基类或超类。因为RangeValidator是一种校验器,OddEvenvalidator也是一种校验器。当一个子类继承自一个基类时,它可以做基类能做的任何事情,因此RangeValidator和OddEvenValidator都是Validator的扩充。

虽然父类和子类的类型不一样当通过继承将不同类的共同属性和行为抽象为一个公共的基类后于是它们就具有了共同的属性和行为这就是OOP通过继承实现代码重用的方法。因为抽象类在概念上定义了相似的一组类的共同属性和方法,因而能够将这一组相关类看成一个概念。也就是说,抽象类代表了将所有派生类联系起来的核心概念,也正是这个核心概念定义了派生类的共性。同时还提供了与这一组相关类的通信接口规约,然后每个具体类都按需要提供特定的实现。

由此可见,对于一个新的抽象,必须将它放在已经设计好的类和对象层次结构的上下文中。实际上,这既不是自上而下的活动,也不是自下而上的活动。Halbert和O 'Brien指出,“当在一个类型层次结构中设计类时,并非总是从基类开始,然后创建子类。通常会创建一些看起来不相似的类型,当意识到它们是相关时,然后才将它们的共性分离出来,放到一个基类或多个基类中……”实践经验证明,类和对象的设计是一个增量、迭代的过程。Stroustrup认为,“最常见的类层次结构的组织方式是从两个类中提取公共部分放到一个新类中,或将一个类拆分为两个新类。” 比如,将RangeValidator和OddEvenValidator的共性上移到Validator中。

由于许多开发者常常忽略了为对象和类正确地命名,因此必须确保创建类、属性和方法名时,不仅要遵循约定,还要让名字具有描述性,让人一目了然。否则解释权在程序员自己,因为程序员的个性,时常有可能创建一些只对他们自己很有道理的约定,而其他人却完全不能理解。类名不能为动词,类名应该用常见的名词命名,比如,Validator或RangeValidator,避免使用Manager、Processor、Data或Info这样的类名。对象名应该用合适的名词短语命名,比如,rangeValidator或oddEvenValidator。特别地,选择的名字应该是业务领域专家使用和认知的名字。方法名应该是动词或动词短语,比如,pushWithValidate。

当开发者决定采用某种协作模式后,工作会被分解给对象,即在相应的类上定义适当的方法。归根到底,单个类的协议包含了实现所有行为,以及实现与其实例相关的所有机制所需要的全部操作。因此与类层次结构的设计一样,机制代表了战略的设计决策。

实际上,机制就是在长期的实践中发现和总结的各种模式。在底层开发模式中,惯用法是一种表现形式;在高层开发模式中,则有一组类组成的框架。框架代表了大规模的复用,比如,ZLG的AMetal框架和AWorks框架,MVC框架和MVVM框架以及微软的.NET框架或开源代码。所以机制代表了一种层次的复用,它高于单个类的复用。

虽然代码表明了基类与子类的关系,但还是不够深刻。在这里,将以Validator与RangeValidator之间的继承关系为例,通过UML图进一步形象地描述

继承关系为何指向基类?其深刻的设计思想是它代表了依赖的方向。所谓依赖关系是指两个元素之间的一种关系,其中一个元素变化将会引起另一个元素变化。UML图中采用从子类指向基类的空心箭头表示继承,暗示基类的变化可能导致子类的变化。简而言之,被依赖的先构造,依赖于其它元素的后构造。

其实继承是一个非常传统和经典的术语,从Smalltalk问世时就被广泛使用,将一般类和它的特殊类之间的关系称为继承关系。它在很多场合还以动词或形容词的面目出现。比如,特殊类继承了一般类的属性和操作,面向对象编程语言具有继承性和封装性等。

而一般-特殊恰当地一般类和它的特殊类之间的相对关系,既可以称为一般-特殊关系,也可以形成一般-特殊结构。当“一般”这个术语generalization翻译成中文时,很容易与上下文混淆,因此翻译成“泛化”更准确。即一般类(父类)对特殊类(子类)而言是泛化,反之就是特化。因此一般类和特殊类之间的关系称为一般-特殊关系,一般-特殊结构是由一组具有一般-特殊关系(继承关系)的类所形成的结构。

显而易见,一般-特殊结构是问题域中各类事物之间客观存在的一种结构,在面向对象分析模型中建立一般-特殊结构,使模型更清晰地映射了问题域中事物的分类关系——将对象划分为类,用类描述属于它的全部对象实例。它将具有一般-特殊关系的类组织在一起,可以简化对复杂系统的认识,使人们对系统的认识和描述更接近日常思维中一般概念和特殊概念的处理方式。

在面向对象的开发中,一般-特殊结构可以使开发者简化对类的定义,因而对象的共同特征只需在一般类中给出,特殊类通过继承而自动地拥有这些特征,不必再重复定义。

不同的方法学对如何发现一般-特殊结构,有不同的策略。其最大的问题让人们感到更多地是依赖于直觉,如果分析方法是一门艺术,也就意味着让人具有很大的不确定性。而事实上,使用共性和差异化分析工具,并从概念、规约和实现三个不同的视角看待对象,就可以简化复杂的系统,详见《嵌入式软件工程方法与实践丛书——面向对象的分析与设计》。

>>> 1.1.3 职责驱动设计

OO强调的是在现实世界或业务领域中找出软件对象,而软件对象与现实世界中对象的行为完全不一样。软件对象以点对点的通信方式通过发送消息进行交互,而现实世界中的对象与环境的交互,以及其它对象动态地反映现实世界的对象之间交互都要丰富得多。

经验丰富的开发人员在研究领域时,如果发现了他们所熟悉的某种职责或某个关系网,他们会想起以前这个问题是如何解决的。以前尝试过哪些模型?在实现中有哪些难题?它们是如何解决的?先前经历过的尝试和失败的教训,会突然间与新的情况联系起来。

为了真实地反映现实世界中对象的动态交互,要让一个类在不同的系统中重用,则必须在设计类时充分考虑扩展性。经过长期的积累,人们总结了一套用于启发和指导类的设计原则:职责驱动设计——如何为协作中的对象分配职责。

显然,对于rangeValidator对象和oddEvenValidator对象来说,它们的职责分别是对push到栈中的数据进行范围值校验和偶校验,也就意味着必须存在相应的方法。由于每个子类都要对自己的行为负责,因此每个子类不仅要提供一个名为validate的方法,而且必须提供它自己的实现代码。比如,RangeValidator和OddEvenValidator都有一个validate的方法,RangeValidator类包含范围值校验的代码,OddEvenValidator类肯定有奇偶校验的代码。它们都是Validator的子类,必须实现其不同版本的validate。

不言而喻,OOP比POP更直接地表达了校验器的共性:“使用validate函数指针在运行中根据对象的类型调用不同的函数,并通过pThis指针指向当前对象引用校验参数将共同的部分打包在一起形成抽象类。”当它们有了这种共性时,则更容易讨论各种校验器相互之间的差别。

除了变量value之外,RangeValidator类对象的validateRange()校验函数的共性是符合范围值条件的判断处理语句,其可变的是范围值校验参数min和max;OddEvenValidator类对象的validateOddEven()校验函数的共性是符合偶数值条件的判断处理语句,其可变的是偶校验参数isEven。

根据共性和可变性分析原理,将稳定不变的相同的处理部分都包含在抽象的模块中,可变性分析所发现的变化的变量由外部传递进来的参数应对。其函数原型如下:

bool validateRange(Validator *pThis, int value);

bool validateOddEven(Validator *pThis, int value);

由于&rangeValidator.isa、&oddEvenValidator.isa和pThis值相等,且类型也相同,因此可以将范围值校验和奇偶校验函数的void *泛化为Validator *。当将一个基类对象替换成它的子类对象时,程序将不会产生任何错误和异常,且使用者不必知道任何差异,反过来则不成立。也就是说,如果某段代码使用了基类中的方法,必须能使用派生类的对象,且自己不必进行任何修改。因此在程序中要尽量使用基类类型定义对象,在运行时再确定其子类类型,用子类对象替换基类对象。这就是里氏替换原则,它是由2008年图灵奖获得者,美国第一位计算机科学女博士Barbara Liskov教授和卡耐基梅隆大学Jeannette Wing教授于1994年提出的。

在应用里氏替换原则时,应该将父类设计为抽象类或接口,让子类继承父类或实现父类接口,并实现在父类中声明的方法。在运行时子类实例替换父类实例,可以很方便地扩展系统的功能。无须修改原有子类的代码,增加新的功能可以通过增加一个新的子类实现,由此可见,里氏替换原则是实现开闭原则的重要方式之一。

如果开闭原则是面向对象设计的目标,那么依赖倒置原则就是面向对象设计的主要原则之一,它是抽象化的具体实现。依赖倒置原则要求传递传递参数时或在关联关系中,尽量引用高层次的抽象层类,即使用接口和抽象类进行变量的声明、参数类型的声明、方法返回类型的声明,以及数据类型的转换等,而不要用具体类做这些事。

为了确保该原则的应用,一个具体类应该只实现接口或抽象类中声明过的方法,而不是给出多余的方法,否则将无法调用在子类中增加新的方法。显而易见,在引入抽象层后,将具体类写在配置文件中。如果需求发生改变,则只需要扩展抽象层,修改相应的配置文件即可。而无须修改原有系统的代码,就能扩展系统的功能,满足开闭原则。通常开闭原则、里氏替换原则和依赖倒置原则会同时出现,开闭原则是目标,里氏替换原则是基础,依赖倒置原则是手段,它们相辅相成相互补充,其目标是一致的,只是分析问题的角度不同。

继承是OO建模和编程中被广泛滥用的概念之一,如果违反了LisKov替换原则,继承层次可能仍然可以提供代码的可重用性,但是将会失去可扩展性。因此在使用继承时,要想一想派生类是否可以替换基类。如果不能,则要问一问自己为何使用继承?如果在编写新的类时,还要重用基类代码代码,则要考虑使用组合。

和继承一样,组合也是一种构建对象的机制。如果新类可以替换已有的类,且它们之间的关系可以描述为is-a,则使用继承。如果新类只是使用已有的类,且它们之间的关系可以描述为has-a,则使用组合。相对继承来说,组合更加灵活,适用性也更强。

有关组合的使用方法和示例,将在后续相关的教程中,结合具体的应用予以阐述。

在这里,RangeValidatorOddEvenValidator类扩展了即继承)Validator,其相应的校验器接口的实现详见程序清单 4.9

程序清单 4.9 通用校验器接口的实现(Validator.c)

1    #include "validator.h" 

2

3    bool validateRange(Validator *pThis, int value)

4    { 

5          RangeValidator *pRangeValidator = (RangeValidator *)pThis; 

6          return pRangeValidator -> min <= value && value <= pRangeValidator -> max; 

7    } 

8

9    bool validateOddEven(Validator *pThis, int value) 

10  {

11        OddEvenValidator *pOddEvenValidator = (OddEvenValidator *)pThis;

12        return (!pOddEvenValidator -> isEven && (value % 2)) ||

13             (pOddEvenValidator -> isEven && !(value % 2)); 

14  }

由此可见,抽象是一个强大的分析工具,其强调的什么是共同的,因此共性和差异化分析自然而然地成为了抽象的理论基础。共性分析寻找的是不可能随时间而改变的结构,而可变性分析则要找到可能变化的结构。如果变化是“业务领域”中各个特定的具体情况,那么共性就定义了业务领域中将这些情况联系起来的概念。共同的概念用抽象类表示,可变性分析所发现的变化将通过从抽象类派生而来的具体类实现。共性与可变性分析工具不仅可以指导我们创建抽象类和派生类,而且还可以指导我们建立抽象和接口。那么类的设计过程自然而然地就简化成了两个步骤:

● 在定义抽象类(共性)时,需要知道用什么接口处理这个类的所有职责;

● 在定义派生类(可变性)时,需要知道对于一个给定的特定实现(即变化),应该如何根据给定的规约实现它。

显然,类是一种编程语言结构,它描述了具有相同职责的所有对象。用相同的方式实现这些职责,并共享相同的数据结构。虽然它的内部可能有一些属性,可能有一些方法,但我们只关心对象对自己的行为负责。因为将实现隐藏在接口之后,实际上是将对象的实现和使用它们的对象彻底解耦了。所以只要概念不变,请求者与实现细节的变化隔离开了。

为了便于阅读,程序清单 4.10展示了通用校验器的接口。

程序清单 4.10 通用校验器的接口(validator.h)

1    #pragma once; 

2    #include<stdbool.h>

3

4    typedef struct _Validator{ 

5          bool (*const validate)(struct _Validator *pThis, int value); 

6    }Validator; 

7

8    typedef struct{ 

9          Validator isa; 

10        const int min; 

11        const int max; 

12  } RangeValidator; 

13

14  typedef struct{

15        Validator isa;

16        bool isEven; 

17  } OddEvenValidator; 

18

19  bool validateRange(Validator *pThis, int value);        // 范围校验器函数

20  bool validateOddEven(Validator *pThis, int value);         // 奇偶校验器函数

21  #define newRangeValidator(min, max)    {{validateRange}, (min), (max)}    // 初始化RangeValidator 

22  #define newOddEvenValidator(isEven)  {{validateOddEven}, (isEven)}   // 初始化OddEvenValidator

在这里还是以范围值校验器为例假设min=0,max=9,程序清单 4.10(22)所示的使用名为newRangeValidator的宏将结构体初始化的使用方法如下:

RangeValidator rangeValidator = newRangeValidator(0, 9); 

宏展开后如下:

RangeValidator rangeValidator = {{validateRange}, (0), (9)}; 

其中,外面的{}为RangeValidator结构体赋值,内部的{}为RangeValidator结构体的成员变量isa赋值。即:

rangeValidator.isa.validate = validateRange;

rangeValidator.min = 0; 

rangeValidator.max = 9;

如果有以下定义

Validator *pValidator = (Validator *)&rangeValidator; 

即可用pValidator引用RangeValidatorminmax

由于pValidator与&rangeValidator.isa不仅类型相同,而且它们的值相等,则以下关系同样成立:

Validator * pValidator = &rangeValidator.isa; 

因此可以利用这一特性获取validateRange()函数的地址,即pValidator->validate指向validateRange()。其调用形式如下:

pValidator -> validate(pValidator, 8); 

此时此刻,也许你会想到,既然它们的方法都一样,只是属性不同,为何不将它们合并为一个类呢?如果这样做的话,则一个类承担的职责越多,它被复用的可能性就越小。而且一个类承担的职责过多,就相当于将这些职责耦合在一起。当其中一个职责变化时,可能会影响其它职责的运作,因此要将这些职责进行分离,将不同的职责封装在不同的类中,即将不同的变化原因封装在不同的类中。如果多个职责总是同时发生变化的话,则可以将它们封装在同一个类中。

也就是说,就一个类而言,应该只有一个引起它变化的原因,这就是单一职责原则,它是实现高内聚、低耦合的指导方针。这是最简单也最难运用的原则,需要开发人员发现类的不同职责并将其分离。

>>> 1.1.4 多态性

多态性是面向对象程序设计的一个重要特征,多态(函数)的字面含义是具有多种形式。每个类中操作的规约都是相同的,而这些类可以用不同的方式实现这些同名的操作,从而使得拥有相同接口的对象可以在运行时相互替换。

当向一个对象发送一个消息时,这个对象必须有一个定义的方法对这个消息作出响应。在继承层次结构中,所有子类都从其超类继承接口。由于每个子类都是一个单独的实体,它们可能需要对同一个消息作出不同的响应。比如,Validator类和行为validate。

在面向对象的编程中,真正引用的是从抽象类派生的类的具体实例。当通过抽象引用概念要求对象做什么时,将得到不同的行为,具体行为取决于派生对象的具体类型。因此,为了描述事物之间相同特性基础上表现出来的可变性,于是多态就被创造出来了,多态允许用相同的方法(代码)处理不同行为的对象。

多态是一种运行时基于对象的类型发生的绑定机制,通过这种机制实现函数名绑定到函数具体实现代码的目的。当执行一个程序时,构成程序的各个函数分别在计算机的内存中拥有了一段存储空间,一个函数在内存中的起始地址就是这个函数的入口地址,因此多态就是将函数名动态绑定到函数入口的运行时绑定机制。尽管多态与继承紧密相关,但通常多态被单独看作面向对象技术最强大的一个优点。

显然,调用校验器就是发送一个消息,它要使用validate函数指针实际上无论范围值校验器还是奇偶校验器其校验过程都是由不同内容的函数实现的。在面向对象的编程中,在不同的类中定义了其响应消息的方法,那么在使用这些类时,则不必考虑它们是什么类型,只要发布消息即可。正如在调用校验器时,不必考虑其调用的它们是什么校验器,直接使用validate函数指针,无论什么类型校验器都能实现检查功能。

由于RangValidatorOddEvenValidator都继承自Validator因此没有必要在继承树中对每一种校验器都重复定义这些属性和行为,重复不仅需要做更多的事情,甚至还可能导致错误和出现不一致,详见图 4.5。这种关系在UML中表示为一条线,并有一个箭头指向父类。这种记法非常简明扼要,当遇到这种带箭头的线时,就知道存在一个继承并呈现多态的关系。

图 4.5 抽象类的层次结构

在设计Validator时,对各种校验器的使用进行标准化会有很大的帮助,因为无论是何种校验器,都用一个名为validate的方法。如果遵循这个规范,不管什么时候校验数据,只需要调用validate方法即可。无需考虑这到底是什么校验器,于是就有了一个真正多态的Validator框架——由各个对象自己负责完成校验,不论它是范围值校验、奇偶校验还是质数校验。

根据开闭原则,需要再编写一个扩展push功能的pushWithValidate()函数,其原型如下:

bool pushWithValidate(stackADT stack, int value, Validator *pValidator); 

如果需要进行范围值校验,则pValidator指向rangeValidator,否则将pValidator置NULL。

pushWithValidate()的具体实现如下:

1    bool pushWithValidate(stackADT stack, int value, Validator *pValidator) 

2    { 

3          if (pValidator && !pValidator -> validate(pValidator, value)){ 

4               return false; 

5         }

6          return push(stack, value);

7    }

其调用形式如下:

pushWithValidate(stack, 8, &rangeValidator.isa);

使用通用校验器的应用范例程序详见程序清单 4.11

程序清单 4.11 使用通用校验器的范例程序

1    #include<stdio.h>

2    #include"Stack.h"

3    #include"validator.h" 

4

5    bool pushWithValidate(stackADT stack, int value, Validator *pValidator)

6    { 

7          if (pValidator && !pValidator -> validate(pValidator, value)){ 

8               return false; 

9         }

10        return push(stack, value); 

11  }

12

13  int main(int argc, int *argv[]) 

14  {

15        stackADT stack; 

16        int temp;

17

18        stack = newStack();

19

20        RangeValidator rangeValidator = newRangeValidator(0, 9);

21        for (int i = 0; i < 16; i++){ 

22             pushWithValidate(stack, i, &rangeValidator.isa); 

23        }

24        while(!stackIsEmpty(stack)){ 

25             pop(stack, &temp);

26             printf("%d ", temp);

27        } 

28        printf("\n");

29        OddEvenValidator oddEvenValidator = newOddEvenValidator(true);

30        for (int i = 0; i < 16; i ++){ 

31             pushWithValidate(stack, i, &oddEvenValidator.isa);

32        } 

33        while (!stackIsEmpty(stack))   { 

34             pop(stack, &temp); 

35              printf("%d ", temp);

36        }

37        freeStack(stack); 

38        return 0; 

39  }

由此可见,虽然OOA和OOD的边界是模糊的,但它们关注的重点不一样。OOA关注的是分析面临的问题域,从问题域词汇表中发现类和对象,实现对现实世界的建模。OOD关注的是如何设计泛化的抽象和一些新的机制,规定对象的协作方式。

热门推荐

原文标题:周立功:继承与多态

文章出处:【微信号:Zlgmcu7890,微信公众号:周立功单片机】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
分享:

评论

相关推荐

PICmicro中档单片机系列之在线串行编程

本文主要介绍了PICmicro中档单片机系列之在线串行编程。

发表于 06-25 04:20 ? 10次 阅读
PICmicro中档单片机系列之在线串行编程

一种将源程序编译生成的固件烧录到目标芯片设计

编程器作为一种量产型生产工具,研发工程师一般对其知之甚少,但它对产线的生产影响却很大。如果因编程器本....

的头像 ZLG致远电子 发表于 06-17 19:25 ? 994次 阅读
一种将源程序编译生成的固件烧录到目标芯片设计

PICkit 3编程器作为开发工具在目标板上仿真和调试固件的方法详细概述

本文档说明了使用 PICkit 3 作为开发工具在目标板上仿真和调试固件的方法。PICkit 3 编....

发表于 06-14 09:27 ? 18次 阅读
PICkit 3编程器作为开发工具在目标板上仿真和调试固件的方法详细概述

电机控制入门工具包的中文使用手册免费下载

 工具包中提供的电路板用于介绍和演示低成本 16 位电机控制和 mTouch? 系列器件的功能和特性....

发表于 06-14 09:27 ? 46次 阅读
电机控制入门工具包的中文使用手册免费下载

MPLAB串行存储器产品入门工具包的详细中文资料概述

MPLAB 串行存储器产品入门工具包是一款易于使用且功能强大的工具,方便用户对串行存储器应用进行设计....

发表于 06-14 08:27 ? 21次 阅读
MPLAB串行存储器产品入门工具包的详细中文资料概述

带看门狗功能的专用复位芯片设计方案

在产品规划中,如使用芯片内部集成的DCDC模块给系统的各个子模块(如内存、电子硬盘、硬件看门狗等)供....

的头像 周立功单片机 发表于 06-13 09:16 ? 589次 阅读
带看门狗功能的专用复位芯片设计方案

AWorks软件设计,邮箱、消息队列和自旋锁使用方法

本文介绍了邮箱、消息队列和自旋锁的使用方法。信号量只能用于任务间的同步,不能传递更多的信息,为此,A....

的头像 ZLG致远电子 发表于 06-13 09:13 ? 1062次 阅读
AWorks软件设计,邮箱、消息队列和自旋锁使用方法

如何使用PICkit 3作为开发工具在目标板上仿真和调试固件的中文概述

本文档介绍了如何使用 PICkit 3 作为开发工具在目标板上仿真和调试固件,以及如何烧写器件。 ....

发表于 06-08 17:28 ? 32次 阅读
如何使用PICkit 3作为开发工具在目标板上仿真和调试固件的中文概述

面向AWorks框架管理文件的方法和数据结构

文件系统是在存储设备中(SD Card、NAND Flash…)组织文件的方法和数据结构,用于管理文....

的头像 ZLG致远电子 发表于 06-05 09:18 ? 794次 阅读
面向AWorks框架管理文件的方法和数据结构

干货!大神自制51编程器

AT89C51是一款应用最为广泛的8051单片机,更重要的是他具有反复烧写(FLASH)的特性。一般....

发表于 05-29 10:44 ? 152次 阅读
干货!大神自制51编程器

MPLAB? PM3器件编程器用户指南(用于MPLAB X IDE)

MPLAB? PM3器件编程器用户指南(用于MPLAB X IDE)

发表于 05-25 17:29 ? 35次 阅读
MPLAB? PM3器件编程器用户指南(用于MPLAB X IDE)

一个高集成度的掉电检测电路应用

对于核心板的嵌入式系统来说,异常掉电情况下数据不丢失,稳定性是根本。本文基于CAT706介绍一种能够....

的头像 周立功单片机 发表于 05-25 09:35 ? 1942次 阅读
一个高集成度的掉电检测电路应用

AWorks对常见的外部通用设备接口应用

AWorks对常用的硬件设备(LED、按键、蜂鸣器、数码管等等)进行了抽象,分别为每一类设备提供了通....

的头像 周立功单片机 发表于 05-24 09:44 ? 1296次 阅读
AWorks对常见的外部通用设备接口应用

M105x系列跨界硬件核心板嵌入式开发

迄今为止,知道AWorks的开发者越来越多,却只有极少数了解其精髓,在即将发布之际,周立功教授及其团....

的头像 周立功单片机 发表于 05-23 09:18 ? 1387次 阅读
M105x系列跨界硬件核心板嵌入式开发

全新的物联网操作系统AWorks IoT OS

Wi-Fi、zigbee、NFC、LoRa等无线技术使用得十分广泛,但无线电路设计存在诸多难点:天线....

的头像 ZLG致远电子 发表于 05-22 08:57 ? 2622次 阅读
全新的物联网操作系统AWorks IoT OS

i.MX28x系列无线工控板中的IoT-A28LI主板整体布局

基于AWorks平台的ARM9与Cortex-A系列工控主板,具有丰富的扩展接口,可以扩展zigbe....

的头像 ZLG致远电子 发表于 05-19 08:56 ? 1180次 阅读
i.MX28x系列无线工控板中的IoT-A28LI主板整体布局

基于AWorks平台A3352系列无线核心板设计方案

基于AWorks平台的A6G2C(Cortex-A7内核)与A3352(Cortex-A8内核)系列....

的头像 ZLG致远电子 发表于 05-18 08:56 ? 943次 阅读
基于AWorks平台A3352系列无线核心板设计方案

M3352核心板及评估底板及产品设计框图

为了便于用户快速开发产品,ZLG致远电子研发设计了基于AWorks平台的,集MCU、DDR3、Nan....

的头像 周立功单片机 发表于 05-16 09:09 ? 1558次 阅读
M3352核心板及评估底板及产品设计框图

集MCU、DDR、NandFlash、硬件看门狗等等于一体核心板

为了便于用户快速开发产品,ZLG致远电子研发设计了基于AWorks平台的,集MCU、DDR、Nand....

的头像 周立功单片机 发表于 05-15 09:15 ? 1417次 阅读
集MCU、DDR、NandFlash、硬件看门狗等等于一体核心板

AWorks开发者越来越多,却只有极少数了解其精髓

迄今为止,知道AWorks的开发者越来越多,却只有极少数了解其精髓,在即将发布之际,周立功教授撰写了....

的头像 ZLG致远电子 发表于 05-07 08:34 ? 2072次 阅读
AWorks开发者越来越多,却只有极少数了解其精髓

MSP430单片机BSL编程器使用说明书VER4.3

安装USB驱动程序,安装完成后在Windows的设备管理器中查看串口序号。

发表于 05-04 17:34 ? 80次 阅读
MSP430单片机BSL编程器使用说明书VER4.3

周立功的AWorks哲学思想

苹果之所以成为全球最赚钱的公司,关键在于产品的性能超越了用户的预期,且因为大量可重用的核心领域知识,....

的头像 人间烟火123 发表于 05-04 14:38 ? 1765次 阅读
周立功的AWorks哲学思想

基于Ametal平台开发,快速完成开发设计!

传统旋钮采用机械式结构,面板上需要开孔,长时间使用易磨损、进灰尘等,采用新型吸附式磁旋钮可以轻松解决....

的头像 周立功单片机 发表于 05-04 09:11 ? 1731次 阅读
基于Ametal平台开发,快速完成开发设计!

隔离电源自主搭建VS模块方案设计

电源是电子系统的心脏,工业应用中,为系统前级或接口供电的电源一般都要求有高的抗干扰性能,各种隔离型的....

的头像 ZLG致远电子 发表于 04-27 08:46 ? 1986次 阅读
隔离电源自主搭建VS模块方案设计

容量Flash器件编程设计,体验极速高效的全新烧录感受!

它拥有极致速度、高效压杆;它自带独立操作系统,省去PC机方便产线部署;它拥有独特的母片分析”“文件分....

的头像 周立功单片机 发表于 04-24 08:42 ? 1899次 阅读
容量Flash器件编程设计,体验极速高效的全新烧录感受!

VER8.0 IP硬盘编程器资料下载

VER8.0 IP硬盘编程器资料下载

发表于 04-23 09:37 ? 42次 阅读
VER8.0 IP硬盘编程器资料下载

KIT下载软件安装与使用图解

下载完成后必须按照说明书使用杜邦线将芯片指定引脚连接到相应的功能模块对应IO引脚,才能看到程序正常运....

的头像 畅学单片机 发表于 04-17 16:46 ? 689次 阅读
KIT下载软件安装与使用图解

eMMC海量烧录困境,你真的知道吗?

随着智能手机、平板电脑等智能终端性能的快速提升,以及智能硬件设备的应用普及,设备对存储器件的要求越来....

的头像 ZLG致远电子 发表于 04-13 08:39 ? 2251次 阅读
eMMC海量烧录困境,你真的知道吗?

隔离反激和非隔离BUCK应用设计方案

在产品设计时,倘若没有考虑应用环境对电源隔离的要求,产品到了应用时就会出现因设计方案的不当导致的系统....

的头像 周立功单片机 发表于 04-13 08:35 ? 2306次 阅读
隔离反激和非隔离BUCK应用设计方案

你不知道的单片机编程器分类

兼容microChip的PICKIT2,是一款低成本开发工具,带有易于使用的用户界面,用于为微芯闪存....

发表于 04-12 11:10 ? 360次 阅读
你不知道的单片机编程器分类

编程器哪个牌子的好_编程器品牌排名介绍

本文主要介绍了八个编程器品牌排名。编程器为可编程的集成电路写入数据的工具,编程器主要用于单片机或存储....

的头像 电子魔法师 发表于 04-10 17:21 ? 1552次 阅读
编程器哪个牌子的好_编程器品牌排名介绍

MSP430开发工具的介绍及其特性

在MCU项目开发过程中,始终有两个设备紧密的联系在一起,一个是仿真器,一个是编程器。仿真器,顾名思义....

的头像 汽车玩家 发表于 04-10 16:26 ? 740次 阅读
MSP430开发工具的介绍及其特性

单片机的编程器和烧录器有什么区别

本文开始介绍了单片机编程器的特点以及对单片机编程器作用及功能进行了解析,其次介绍了烧录器的概念以及它....

的头像 电子魔法师 发表于 04-09 10:36 ? 1201次 阅读
单片机的编程器和烧录器有什么区别

欧姆龙手持编程器使用说明

本文开始介绍了编程器的概念和编程器的使用方法,其次阐述了编程器写存储器方法,最后介绍了欧姆龙手持编程....

的头像 电子魔法师 发表于 04-09 10:14 ? 1016次 阅读
欧姆龙手持编程器使用说明

怎么用编程器刷bios

想要支持新U,就得刷新BIOS,不过超微初涉民用主板领域,在这方面明显没有一线厂家经验丰富,所以本人....

的头像 电子魔法师 发表于 04-09 09:54 ? 1041次 阅读
怎么用编程器刷bios

编程器固件和路由器固件什么不同

本文开始阐述了固件的概念,其次介绍了固件的工作原理与固件的技术性能,最后详细的介绍了编程器固件和路由....

的头像 电子魔法师 发表于 04-09 09:38 ? 1763次 阅读
编程器固件和路由器固件什么不同

编程器怎么用_编程器的使用方法

本文开始介绍了编程器概念和编程器写存储器方法,其次介绍了编程器的使用方法与USB口24系列编程器使用....

的头像 电子魔法师 发表于 04-09 09:16 ? 1053次 阅读
编程器怎么用_编程器的使用方法

解决芯片量产问题,MCU成最大焦点

随着越来也多的电子厂商不断为物联网(IoT)推出新产品,全球MCU出货量正出现巨大成长动能。特别是当....

的头像 ZLG致远电子 发表于 03-30 08:49 ? 2377次 阅读
解决芯片量产问题,MCU成最大焦点

滤芯防伪技术,可以分布式读取8处防伪标签

空气净化器、净水器市场发展迅猛,很多品牌商都抢占到了自己的份额。但在实际使用过程中却发现很多用户长期....

的头像 周立功单片机 发表于 03-28 08:29 ? 1289次 阅读
滤芯防伪技术,可以分布式读取8处防伪标签

一款跨界核心板,让物联网设计如MCU系统便捷

M1052跨界核心板让设计者如开发普通MCU系统般简便,却拥有528MHz主频处理器的“不凡”性能。

的头像 ZLG致远电子 发表于 03-23 08:29 ? 4174次 阅读
一款跨界核心板,让物联网设计如MCU系统便捷

周立功现身说法:谈工程师如何克服职业痛点培养对市场的前瞻性

为什么很多工程师创业失败?其根本原因不是资金,而是因为不了解市场,对市场缺乏一定前瞻性的认识,做出来....

的头像 工程师人生 发表于 03-14 10:53 ? 613次 阅读
周立功现身说法:谈工程师如何克服职业痛点培养对市场的前瞻性

ZLG携手NXP举行i.MX RT 跨界处理器全国巡回研讨会

2018年3月20号—4月3号,ZLG将携手NXP在全国6大城市(广州、深圳、上海、杭州、南京、北京....

的头像 ZLG致远电子 发表于 03-09 15:24 ? 1517次 阅读
ZLG携手NXP举行i.MX RT 跨界处理器全国巡回研讨会

土豪金编程器使用教程

编程器使用教程

发表于 03-08 10:10 ? 198次 阅读
土豪金编程器使用教程

MCU+MPU双处理器架构在电力馈线终端中应用

目前市面上大多电力FTU产品均采用MCU+MPU双处理器架构,以利用MCU的实时性和MPU上运行的稳....

的头像 周立功单片机 发表于 03-05 08:41 ? 1844次 阅读
MCU+MPU双处理器架构在电力馈线终端中应用

工业通讯现场,为何最担心浪涌产生的瞬态过压和过流!

各位工程师在工业通讯现场,最担心的是通讯网络因浪涌产生的瞬态过压和过流,导致总线通讯网络出现发送错误....

的头像 周立功单片机 发表于 02-28 08:42 ? 1726次 阅读
工业通讯现场,为何最担心浪涌产生的瞬态过压和过流!

PICkit2的使用技巧和方法

PICkit 2开发编程器/调试器是一款低成本开发编程器。它能够对Microchip的大多数闪存单片....

的头像 PoisonApple 发表于 02-27 11:26 ? 858次 阅读
PICkit2的使用技巧和方法

组建RS-485总线网络时,终端电阻实战案例

RS-485总线具有结构简单、成本低等优点,但各位工程师在组建RS-485总线网络时,为提升整个网络....

的头像 周立功单片机 发表于 02-08 09:51 ? 2953次 阅读
组建RS-485总线网络时,终端电阻实战案例

基于PLC基础知识的详细解析

可编程逻辑控制器,它采用一类可编程的存储器,用于其内部存储程序,执行逻辑运算、顺序控制、定时、计数与....

的头像 工控云学堂 发表于 01-27 22:59 ? 1680次 阅读
基于PLC基础知识的详细解析

如何使用RTC实时时钟进行应用场景开发

虽然该程序的逻辑与程序清单6.70 所示的应用程序基本一致,但由于使用的接口是特殊功能控制接口,与具....

的头像 周立功单片机 发表于 01-25 09:15 ? 2421次 阅读
如何使用RTC实时时钟进行应用场景开发

13.56MHz读写卡模块通信接口及选型指南

论选择I2C 或UART 通信方式,只要基于实例句柄编程,则应用程序与具体的通信方式无关。

的头像 周立功单片机 发表于 01-25 09:09 ? 2620次 阅读
13.56MHz读写卡模块通信接口及选型指南

labview上位机,周立功USBCAN1卡,传输指令给电机驱动器

发表于 01-07 13:00 ? 639次 阅读
labview上位机,周立功USBCAN1卡,传输指令给电机驱动器

周立功:基于平台的产品开发战略

发表于 12-11 16:03 ? 731次 阅读
周立功:基于平台的产品开发战略

LPC入门起步探讨,感觉LPCOpen例程包最好用

发表于 11-27 01:06 ? 1328次 阅读
LPC入门起步探讨,感觉LPCOpen例程包最好用

基于周立功CAN卡例程,显示某一特定ID报文数据的实时性问题

发表于 10-19 09:42 ? 782次 阅读
基于周立功CAN卡例程,显示某一特定ID报文数据的实时性问题

【下载】新书速递:周立功教授心血新力作《面向AMetal框架与接口的编程(上)》

发表于 08-22 17:56 ? 5004次 阅读
【下载】新书速递:周立功教授心血新力作《面向AMetal框架与接口的编程(上)》

新书速递:周立功教授心血新力作《面向AMetal框架与接口的编程(上)》

发表于 08-21 14:58 ? 867次 阅读
新书速递:周立功教授心血新力作《面向AMetal框架与接口的编程(上)》

庆祝周立功顺利入驻硬之城,优势料号大放送!

发表于 06-16 14:01 ? 665次 阅读
庆祝周立功顺利入驻硬之城,优势料号大放送!

【下载】ARM嵌入式系统基础教程(周立功第2版)

发表于 06-12 17:59 ? 6844次 阅读
【下载】ARM嵌入式系统基础教程(周立功第2版)

ARM嵌入式系统基础教程(第二版)周立功

发表于 05-24 15:00 ? 1604次 阅读
ARM嵌入式系统基础教程(第二版)周立功

【完整资料】《程序设计与数据结构》周立功数十年心血力作

发表于 05-16 16:43 ? 44971次 阅读
【完整资料】《程序设计与数据结构》周立功数十年心血力作
小管公 2013年8月黄道吉日 后街居委会 属马和什么属相相冲 风水宝地
五行属土缺火 寿民路 1984年生人运程 大门朝向风水 周易大师1 双柳树胡同 2014年属马运程 流水风水
1 4 15 17 16
熟食培训 仪表 养生 传感器 宠物 讨债 励志名言 手游游戏 名人名言 散文 离心机 育儿 空调 真空泵 空压机 超声波清洗机 纺织 建筑装饰 机械 五金 铜价 空调 减肥 养生网 整形美容 真人娱乐网 时尚女人 机械门户网 债务维权 侦探 空调维修 家电维修 空调维修制冷 机械网 娱乐新闻 怀孕知识 快递公司 汽车论坛 天下奇闻 风水 婚纱摄影 两性知识 说话技巧 包包 健康门户 金融理财 军事 陶瓷 高校招生 移动通信 时尚女人 股票行情 塑料 体育新闻 电影 健康小常识 服装品牌 科技新闻 生理健康 女性时尚 寺庙 免费算命 星座运势 儿童教育 旅游 历史文化 艺考 今日新闻 化妆品 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 Wika压力表 wika压力表 wika压力表 wika压力表 wika压力表 电伴热厂家 天然气锅炉 罗斯蒙特压力变送器 冷热一体机玻璃钢格栅 恒功率电伴热带 磁翻板液位厂家 铠装热电偶 消防车卷帘门 密度计生产厂家 不锈钢压力表 LED电源厂家 电源外壳 在线密度计 特种电缆 铂铑热电偶 耐震压力表 生物质锅炉 有机玻璃管 亚克力管 生物质热风炉 wika 威卡 wika压力表 威卡压力表 威卡 智能型压力变送器 安徽天康股份有限公司 流量计生产厂家 拉丝模 开关柜 化工流程泵 流量计生产厂家 电磁流量计厂家 流量计厂家 超声波液位计 消防车铝合金卷帘门 消防车铝合金卷帘门 消防车卷帘门 消防车卷帘门 消防车卷帘门 计算机电缆 流量计厂家 超声波液位计 智能型扩散硅压力变送器 开关柜 超声波液位计 智能型压力变送器 安徽天康 流量计生产厂家 压力表厂家 不锈钢压力表 有机玻璃管 计算机电缆 自限温电伴热带