算法是脊,数据是肉;思想是鸡,结论是蛋——题记

冒号重新开讲:“你们会不会经常遇到这种情景:一遍又一遍地写着相似的代码,有心将其归并,却因种种原因无法践行。”

逗号心有戚戚焉道:“是啊,有时明明两个函数的实现几乎一模一样的,就因为某些参数不匹配,无法合而为一。”

“有一种编程范式可以解决这个问题,它打破了不同数据结构之间的壁垒,让你的代码不再臃肿,这——就是泛型编程。”冒号的语调和说辞不免令人联想到电视上的减肥广告,“Generic Programming,简称GP,其基本思想是:将算法与其作用的数据结构分离,并将后者尽可能泛化,最大限度地实现算法重用。这种泛化是基于模板的参数多态(parametric polymorphism),相比OOP基于继承的子类型多态(subtype polymorphism),不仅普适性更强,而且效率也更高。这不能不说是一种异数——我们知道,普适性往往是以效率为代价的。GP最著名的代表是C++中的STL,其后亦为Java,C#等所吸纳。此外,一些函数式语言如Ocaml、Standard ML、Generic Haskell等也支持GP。”

冒号写下两段代码——

C++(泛型编程):

template

T max(T a, T b)       //求出两个数中的较大者

{

return (a > b) ? a : b;

}

C(宏定义):

#define max(a,b) ((a) > (b) ? (a) : (b))

“求两个数中的较大值是经常遇到的问题。”冒号解说着,“对于静态类型语言来说,若参数类型不同,即使函数体相同也不能合为一体。如果语言不支持重载(overload),还可能出现maxInt、maxLong、maxFloat、 maxDouble之类的函数名,冗赘而丑陋。尽管在C中可用宏定义来实现,但无法保证类型安全,而C++模板则兼顾类型安全和代码重用,并且由于是在编译期间展开的,效率上也不损失。不止于此,C++支持运算符重载,除数值类型外,一切定义了‘>’ 运算的数据类型均可调用max函数,真是一举N得,N趋向无穷大啊!”

冒号边说边比划,夸张的语气和手势逗得大家都笑了。

引号提出疑问:“Java的一切对象都是Object,将所有参数都换成Object类型,岂不也是一种泛化?”

冒号答道:“首先,基本类型如int,float等不是Object的子类,虽然Java 新增了自动装拆箱(autoboxing/unboxing)的功能,但要付出性能的代价。更重要的是,这将不可避免地需要类型强制转换,丧失了静态类型语言的优势,为Bug大开方便之门。这也是Java最终引入模板的原因,虽然有些姗姗来迟。类似地,C/C++中的通用指针void *也有类型安全问题。”

句号发表他的看法:“泛型虽好,似乎只是某些局部才用到的技术,不具有前面几种范式的渗透性。”

冒号听罢不语,返身在黑板上写下几道题——

1.从一个整数数组中随机抽取十个数,对其中的素数求和

2.将一个无序整数集中所有的完全平方数换成其平方根

3.从学生成绩表中,列出门门都及格且平均分在70分以上的学生名单

4.在一个着色二元树中,将所有的红色结点涂成蓝色

5.将一个字符串从倒数第三个字符开始反向拷贝到另一个字符串中

6.每从标准输入读取一个非数字的字符,于标准输出打印‘请输入数字’

句号暗忖,不过是些常规题嘛。不料冒号的问题却出人意表:“请问它们之间有何共同之处?能否共享一段代码?”

见众人缄默已久,冒号接着投影出一段代码——

template

void process(Iterator begin, Iterator end, Act act, Test test)

//对容器中在给定范围内(即起于begin止于end)所有满足给定条件的元

//素(即test(元素)==true)进行处理(即act(元素))

{

for ( ; begin != end; ++begin)    //从头至尾遍历容器内元素

if (test(*begin)) act(*begin); //若当前元素满足条件,则对其采取行动

}

“STL有三要素:算法(algorithm)、容器(container)和迭代器(iterator)。容器是数据的集合,可理解为抽象的数组;迭代器是算法与容器之间的接口,可理解为抽象的指针或者游标。”冒号讲述道,“算法串联数据,如脊贯肉;数据实化算法,如肉附脊。只有抽象出表面的数据,算法的脊梁才能显现。以上几题看似风马牛不相及,若运用泛型思维,便可发现它们的共性:对指定集合中满足指定条件的元素进行指定处理。用模板语言,寥寥数行即勾勒完毕。”

问号诧异道:“相比前面的max模板,这里连元素的数据类型T都不见了?”

冒号回答:“元素被容器封装了。”

问号追问:“可这里连容器也看不到啊?”

冒号料有此问:“容器通过它的迭代器参与算法。”

句号豁然开朗:“通过模板,泛化了容器——可以是数组、列表、集合、映射、队列、栈、字符串等等;泛化了元素——可以是任何数据类型;泛化了处理方法和限定条件——可以是任何函数。”

冒号提醒道:“补充两点:处理方法和限定条件不限于函数,还可以是函子(Functor)——自带状态的函数对象;另外还有一个隐蔽的泛化:迭代器——可以从前往后移动,可以从后往前移动,可以随机移动,也可以按任意预先定义的规律移动。”

叹号由衷感叹:“果然强悍啊!”

逗号倒也心细:“最后一题中标准输入也算容器吗?”

“为什么不呢?只要一个对象配备了迭代器,它就算容器。I/O流上就有现成的迭代器,当然你也可以自行定制。”冒号目光转向句号,“现在还有人说泛型编程渗透性不强吗?”

句号腆然一笑。

“这只是泛型编程的冰山一角。重要的是,我们不是在玩弄花哨的技巧,而是在用一种新的视角去审视问题。”冒号总结道,“泛型编程是算法导向(Algorithm-Oriented)的,即以算法为起点和中心点,逐渐将其所涉及的数据结构内涵模糊化、外延扩大化,从而扩展算法的适用范围。这非常类似数学思维——当数学家证明完一个定理后,总会试图在保持核心思想的前提下,尽可能地放宽题设,增强结论,从而推广定理。外行人以为数学定理最重要,其实数学思想才是数学的精髓,在数学家眼里,思想是鸡,结论是蛋。这也无怪乎STL会出自一位学数学的人之手了。”

java 范式 问号_冒号和他的学生们(连载9)——泛型范式相关推荐

  1. java 范式 问号_巴科斯范式和扩展巴科斯范式

    巴科斯范式(也称为巴科斯-瑙尔范式.巴克斯-诺尔范式)即 BNF 是一种用于表示上下文无关文法的语言,上下文无关文法描述了一类形式语言.尽管巴科斯范式也能表示一部分自然语言的语法,它还是更广泛地使用于 ...

  2. studentname在java中怎么_是教师,还是学生?setName法和string赋值法区别在哪里!!!...

    [java]代码库import java.util.ArrayList; import java.util.List; //主函数 public class ArrayListDemo { publi ...

  3. Java何为范式_冒号课堂§3.1:泛型范式

    冒号课堂 第三课 常用范式(1) 课前导读 这一课介绍了四个常用的编程范式:泛型式.元编程.切面式和事件驱动式. 本课共分四节-- 1.泛型范式 2.超级范式 3.切面范式 4.事件驱动 3.1泛型范 ...

  4. java 语法 冒号_冒号课堂 - 冒号专栏 - BlogJava

    冒号课堂 新版<冒号和他的学生们> 抽象类型--实中之虚(介绍抽象类型的种类.意义及其用法) •浅显的比方只是门槛前的台阶,借之或可拾级入门,却无法登堂入室 •具体类型是创建对象的模板,抽 ...

  5. java中的双冒号操作符

    java :: Java中的双冒号操作符 </h1><div class="clear"></div><div class="p ...

  6. 《冒号课堂》连载之七——声明范式:目标决定行动

    <冒号课堂>连载之七--声明范式:目标决定行动 2.2  声明范式--目标决定行动 给我一个支点,我能挪动地球. --阿基米德 关键词:编程范式:命令式编程:声明式编程:函数式编程:逻辑式 ...

  7. 逗号表达式 java_c和java中问号表达式与逗号表达式问题

    C语言中的问号表达式. --?--:-- 式A?B:C值为:若A为真,则B:若A为假,则C. 但有一点是值得注意的,那就是问号表达式的结合性,问号表达式是从右往左的运算方向 尤其是当问号表达式嵌套使用 ...

  8. JVM - 结合代码示例彻底搞懂Java内存区域_对象在堆-栈-方法区(元空间)之间的关系

    文章目录 Pre 示例demo 总体关系 代码示例论证 反汇编 Pre JVM - 结合代码示例彻底搞懂Java内存区域_线程栈 | 本地方法栈 | 程序计数器 中我们探讨了线程栈中的内部结构 ,大家 ...

  9. Java计算时间差_传统的SimpleDateFormat类

    Java计算时间差_传统的SimpleDateFormat类 SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM-dd ...

最新文章

  1. DeepMind 的新强化学习系统是迈向通用 AI 的一步吗?
  2. python csv读取-使用python获取csv文本的某行或某列数据的实例
  3. 你知道钓鱼网站的形成步骤吗?一次网络钓鱼演练带你了解(增强安全意识)
  4. hibernate报错 net.sf.json.util.CycleDetectionStrategy$StrictionStrategyRepeatedReferenceAsObject
  5. 电竞人才平均月薪感受下!上海薪资领跑全国
  6. ubuntu apt 卸载 golang
  7. 边界值法中的上点、内点和离点分析
  8. hdu6287 口算训练
  9. Spring MVC 详解
  10. 细思极恐!大数据和机器学习揭示十二星座的真实面目
  11. 安卓版matlab下载,matlab转为app
  12. js 数字金额的转换 (转)
  13. 解析 通证经济的分类及用途
  14. MySQL安装版本Navicat连接报错2509解决方案
  15. HDU-5761-Rower Bo(微分方程)
  16. accept文件上传类型
  17. 双非南京大学计算机夏令营,一名双非生的“失败”保研经历:夏令营不确定是否有保研资格,预推免上岸理想院校!...
  18. 计算机用用技巧,计算机使用技巧介绍汇总
  19. 计算机加密恢复,系统小技巧:BitLocker密钥恢复二三事
  20. TDSQL-C 真·秒级启停:连接断了,又没断

热门文章

  1. linux列表中添加多个元素,这12种方法轻松合并Python中的列表
  2. 第一篇第一章燃烧的基础知识
  3. alfresco 忘记admin密码
  4. 基于AUTOSAR开发工具链的AUTOSAR软件实战开发-软件架构设计(二)
  5. 高中英语怎样学好呀,负基础
  6. 保研计算机英语词汇,保研英语面试离不开的几个话题,回答都给你整理好了
  7. 初学绘画怎么去注意头发的高光和阴影?如何才能画好高光和阴影?
  8. 华为电脑linux装win7不用u盘,华为笔记本开不了机 怎么用u盘安装windows7
  9. 读书笔记——阿里数据中台(第二篇:OneData体系1)
  10. CSS3地图动态实例(圆圈向外扩散)