基于对象和面向对象编程范式辨析和主流编程语言中的应用
前言
本文的目的是想告诉大家,为什么C++的模板这么强大。为什么Ruby的Duck Typing(像鸭子那样编程)这么强大!
基于对象和面向对象编程范式
关于基于对象和面向对象编程范式,我有着不同于传统的理解。我认为我的理解更能体现出这2个范式的本意。
基于对象,就是使用类封装操作和操作依赖的数据。用类来表示一个概念。类的公共成员,包括函数和数据,就是类的接口,也叫作抽象数据类型(ADT)。
面向对象,就是使用类的接口实现机制来表示操作。一个接口使用一组相关的公共函数代表一个概念的操作。一些类实现这个接口。这个实现类可以互换。
在使用中,使用接口的指针或者引用来调用对象。具体的对象是接口的某个实现类。可以不改变代码,仅仅改变实际的对象来实现动态修改系统的行为。
这就是“动态多态”的能力。
面向对象的动态多态能力,使抽象能力比函数更进一步。
动态多态,在实现中是使用了“虚函数”机制来实现的。
对象指向的本类的虚函数表来查得真正需要调用的方法。
语言特性对比表
C++Java       .NET     Ruby           
类型强类型强类型强类型强类型
静态/动态静态静态检验类型动态解释执行动态
支持面向过程是否否否
支持基于对象是否是是
支持范型否是是否
支持模板是否否否
C++通过抽象基类来作为接口,通过对抽象基类的继承来实现这个接口。
Java和.NET都提供了Interface接口类型。实现接口的类实现了这个机制。
所以说,C++,Java,.NET都支持面向对象的编程范式。特别是java,它只支持面向对象(也就是动态多态)这一种编程范式。其他一概不支持!
动态类型语言,如Ruby,JavaScript都没有接口。为什么呢?
考虑一下,动态类型语言尽管有类型。但是变量都是没有类型的。如
//伪代码
Class Dao1{
Public void save(model){
//保存数据
}
}
Class Dao2{
Public void save(model){
//保存数据
}
}
Class Service{
@dao;
Public void save(model){
this.dao.save();
}
}
//调用代码:
New Service(new Dao1).save(model);
New Service(new Dao2).save(model);
这里,Dao1,Dao2这2个类需要实现一个共同的接口吗?
动态类型语言中,尽管对象是有类型的,但是变量(实际是指向对象的指针)是没有类型的。Service类的变量dao可以是任何类型!只要那个对象所属的类型有Public void save(model);这样签名的函数即可!
动态类型语言中,根本不需要Java等静态语言中的接口的概念。这就是动态类型语言著名的Duck Typing“像鸭子一样编程”的理念。
Java这样的静态类型语言当然也有自己的优点。那就是通过强制实现接口。可以保证程序员不会因为笔误而调用错误的类型。
但是,在实践中,动态类型语言的Duck Typing却是更加灵活,更胜一筹!
动态语言既然没有接口,那么它们调用的方法,也就是该类的方法或者继承的方法,就不需要虚函数表,也就不是面向对象的“动态多态”机制了。
Ruby,JavaScript的“多态”机制,是“动态基于对象”的机制。
根据我的定义标准,Ruby,JavaScript等动态类型语言是“基于对象”编程范式的语言。是“动态基于对象”的编程语言。而非面向对象编程语言。
可能你会说,Ruby,JavaScript 都有“继承”的能力,怎么能说它们不是面向对象编程语言呢?
“继承”,只是一种代码重用机制。和编程范式这样的设计问题根本答不上边。甚至,我反对大量使用继承来重用代码(少数特殊情况除外)。我们应该使用“组合”来重用代码。
因为继承会造成类和类之间的实现依赖。而组合就不会有这种依赖关系。我们只要写上一些通道代码就可换取类和类之间的解耦。
好了,现在再让我们看看C++的基于对象的编程范式。
C++的基于对象,就是设计一些类,把函数和函数需要的数据封装在一个类中。但是,如何实现真正的ADT(抽象数据类型)呢?
这样:头文件代表抽象数据类型。实现文件中提供定义。如果一个抽象数据类型需要多个实现呢?
我们为一个类提供几个实现文件。用哪一个就提供哪一个版本。这样显然非常繁琐。事实上也没有人会这样编程!
那怎么办呢?难道C++这样的静态类型语言的“基于对象”编程范式,注定就不能实现多态吗?C++的模板机制解决了这个问题!(在没有彻底搞懂模板之前,我一直用面向对象编程范式使用C++,因此对C++是怨声载道!)
如:
//伪码
Template<tyepe TDao >Class Service{
Private:
TDao* dao=new TDao();
Public:
Void save(Model model){
This->dao->save(model);
}
}
//使用
Model* model=new Model();
Service<Dao>* service=new Service<Dao>();
Service->save(model);
假设Dao这个类有Public:
Void save(Model model);这样签名的方法。
Void save(Model model)这个函数就是TDao这个抽象数据类型(ADT)公布的方法。
任何类只要有这样的方法,就满足TDao这个ADT,就可以在Service模板类中使用!
对照上面Ruby的伪码,我们可以发现:
1,C++的“模板支持的基于对象”的编程范式,仅仅比动态基于对象语言多了模板参数类型的声明。
而且,C++可以直接在模板类内部实例化类型。真正的类型只有在编译时才指定。而动态基于对象的语言因为没有代表类型的符号,不能实例化未知的类型。
2,C++的“模板支持的基于对象”的编程范式,指定了模板参数类型,也就是在编译时需要验证类型。这就比动态基于对象的语言多了编译时静态验证类型这一道关卡,更加安全可靠。
C++中模板之所以伟大,正是因为它是静态语言中支持基于对象编程范式的银弹!
C++的“模板支持的基于对象”的编程范式,令C++拥有了与Ruby等动态基于对象编程语言的多态能力相比肩的顶级语言!
总结
基于对象和面向对象编程共有三种范式。它们提供了强大的动态或者静态多态能力,使用它们编程,将令你的程序面向抽象,易于更换。
1,“模板支持的基于对象”的编程范式。这种编程范式适用于静态类型的语言。提供了静态多态的能力。典型的如C++。
模板不同于范型。模板是一种编译时的代码生成机制。而泛型是对模板的模拟。在java和.net中都使用类型转换机制而不是源代码生成机制来实现。
我认为模板优于范型。.NET的范型实现的要比Java好。.NET中可以使用new()关键字实现在范型类中创建未知类型的对象,而java中不可以。
“模板支持的基于对象”的编程范式实现了编译时静态的多态。具备了强大的静态多态能力。而且生成的代码运行速度快。
缺点是,如果写得不好,容易发生源代码扩张的问题。
2,“静态类型语言”的面向对象的编程范式。这种编程范式适用于静态类型的语言。提供了动态多态的能力。典型的如Java,NET。
使用接口和实现接口的技术,实现了动态多态。并且可以利用静态类型检验的优势,进行更加完善的类型安全检查。
C++也具有进行这一编程范式的能力。但是,C++对于这一编程范式的支持并不是很好。因此,C++编程中,应该优先使用“模板支持的基于对象”的编程范式。然后再考虑使用“静态类型语言”的面向对象的编程范式实现多态。
3,“动态类型语言”的基于对象的编程范式。使用Duck Typing“像鸭子一样编程”的编程理念。这种编程范式适用于动态类型的语言。它们有类型,但是变量不确定类型。典型的如Ruby。这也实现了动态的多态能力。

基于对象和面向对象编程范式辨析和主流编程语言中的应用相关推荐

  1. 我所偏爱的 C 语言面向对象编程范式

    我所偏爱的 C 语言面向对象编程范式 面向对象编程不是银弹.大部分场合,我对面向对象的使用非常谨慎,能不用则不用.相关的讨论就不展开了. 但是,某些场合下,采用面向对象的确是比较好的方案.比如 UI ...

  2. 基于MATLAB的面向对象编程(1)——类,属性,方法

    这里写目录标题 1 入门 1.1 如何把面条抽象成Class 1.2 文件类 2 基于MATLAB的面向对象编程入门 2.1 如何定义一个类(Class) 2.2 创建一个对象 2.3 类的属性 2. ...

  3. R开发(part12)--基于RC的面向对象编程

    学习笔记,仅供参考,有错必纠 参考自:<R的极客理想>-- 张丹 文章目录 R开发 基于RC的面向对象编程 创建RC类和对象 对象赋值 定义对象的方法 RC对象内置方法和内置属性 RC类的 ...

  4. R开发(part11)--基于S4的面向对象编程

    学习笔记,仅供参考,有错必纠 参考自:<R的极客理想>-- 张丹 文章目录 R开发 基于S4的面向对象编程 创建S4对象 访问S4对象的属性 S4的泛型函数 查看S4对象的函数 R开发 基 ...

  5. R开发(part10)--基于S3的面向对象编程

    学习笔记,仅供参考,有错必纠 参考自:<R的极客理想>-- 张丹 文章目录 R开发 面向对象 面向对象的R语言实现 基于S3的面向对象编程 泛型函数和方法调用 查看S3对象的函数 S3对象 ...

  6. 基于对象的JavaScript编程

    基于对象的JavaScript编程 -JavaScript Object-Oriented Programming By-Ryan Frishberg 接触ajax一直不是很深入,然后对于JavaSc ...

  7. Java基于对象基础 基于对象和面向对象的区别(转)

    Java基于对象基础 基于对象和面向对象的区别 JavaScript设计者想把javascript语言设计成基于对象(object-based)的语言,他想把这个与面向对象(object-orient ...

  8. ruby 新建对象_Ruby面向对象编程简介

    ruby 新建对象 by Nishant Mishra 由Nishant Mishra Ruby面向对象编程简介 (An Introduction to Object-Oriented Program ...

  9. 面向过程、基于对象、面向对象、分析

    一:基础概念 1.1 面向过程 "面向过程"(Procedure Oriented)是一种以过程为中心的编程思想.这些都是以什么正在发生为主要目标进行编程,不同于面向对象的是谁在受 ...

最新文章

  1. nagios插件之登陆防火墙实现session监控
  2. [清华集训2016]石家庄的工人阶级队伍比较坚强——三进制FWT
  3. 纪念我曾经的 JAVA 姿势--转
  4. 走近5G云游戏标准制定——握住互联网世界看不见的手
  5. 看完你就晓得正向代理和反向代理了!
  6. 设计模式 - Composite
  7. [css] position跟margin collapse这些特性相互叠加后会怎么样?
  8. wow mysql dbc_DBC中悲观锁介绍附案例详解
  9. 解决在linux环境下面不显示验证码的问题
  10. .Net实现发送邮件功能
  11. python 类 super_python的类的super()
  12. 微信小程序开发详细步骤
  13. 【Qt for Python官方教程】使用pyside6-rcc引入.qrc文件
  14. MQ 消息队列时如何确保消息不丢失
  15. 爱国者(aigo)U391 128G 固态U盘制作PE启动盘
  16. 深度剖析5种最常见的指数估值算法
  17. 解耦电容选型定性与定量分析
  18. 如何申请注册微信公众号
  19. 虫洞和诸多未解之谜有关联吗?
  20. 用HTML+CSS实现一个计科院网站首页静态页面

热门文章

  1. java dart 官司_Dart和Java的区别
  2. Matlab实用程序--图形应用-条形图和阶梯形图
  3. android点击事件的优先级,android中进程的优先级
  4. mysql图标_MySQL 支持 emoji 图标存储
  5. 【论文笔记】Region-based Convolutional Networks for Accurate Object Detection and Segmentation
  6. 深度学习(DL)与卷积神经网络(CNN)学习随笔-05-基于Python的LeNet之CNN
  7. 记录下两个孩子在MineCraft里面还原公寓的经历
  8. 锋利的jquery 知识点总结
  9. 日期格式YYYY-mm-dd HH:MM:SS大小写解释
  10. Java泛型学习资料小汇