标题:
更佳编程之路 第四章 模块与对象 -1
[打印本页]
作者:
look_w
时间:
2018-4-15 20:26
标题:
更佳编程之路 第四章 模块与对象 -1
什么是面向对象编程(OOP)?OOP 是一种用于解决问题的编程方法或通用方法。与之相反,算法是用于解决特定问题的
特定
方法。OOP天生是一种强有力的方法;它往往使过程型和函数型编程方法与该问题较少相关,并且除非它与过程型和函数型编程方法的混合对其极其有益,否则它们之间不会很好地结合在一起。在Perl 中,这种强大的力量有所减弱,但仍然很好地存在着。
本文讨论 Perl 中的 OOP 对比函数型和过程型编程的基本知识,并演示如何在 Perl 程序和模块中使用OOP。请记住,本文只是一篇概述,而不是对 Perl 中 OOP所有方面的详尽解释。这样的详尽解释需要几本书才能讲完,并且已经被写过几次了。有关详细信息,请参阅本文稍后的 。
究竟什么是 OOP?OOP是一种通过使用对象来解决问题的技术。在编程术语中,对象是这样一些实体:它们的特性和行为是解决手头问题所必需的。这个定义本应该更详细些,但是做不到,因为当今计算机行业中OOP 方法的种类之多简直难以想象。
在 Perl 编程环境中,OOP 并不是使用该语言所必需的。Perl 版本 5 和更高版本鼓励使用 OOP,但确切地说不要求这样做。所有Perl 库都是模块,这意味着它们至少使用 OOP 的基本部分。而且,大多数 Perl库都作为对象实现,这意味着用户必须通过良好定义的接口将它们作为具有特定行为和特性的 OOP 实体来使用。
基本的 OO 编程语言特性通常,有三个语言特性是 OOP 编程语言所必需的。它们是继承、多态性和封装。
Perl支持继承。当一个对象(子对象)使用另一个对象作为起点(父对象),并且随后在需要时修改其特性和行为时,就要用到
继承
。子-父关系是OOP 所必需的,因为它使得在其它对象基础上构建对象成为可能。这种重用是使 OOP 成为程序员宠儿的好处之一。
有两种继承:单一继承和多重继承。
单一继承
要求子对象只有一个父对象,而
多重继承
更自由(与实际生活一样,在编程过程中具有两个以上的父对象会导致混乱并使子对象难以工作,因此,不要过多使用多重继承)。尽管两个或两个以上的父对象实际上很少见,但Perl 支持多重继承。
多态性(来自希腊语,表示“很多形态”)是使一个对象被看成另一个对象的技术。这有点复杂,那么我举个例子。比方说,您有一个绵羊牧场,里面有四只绵羊(绵羊属),但是您刚刚买了两只山羊(山羊属)和一只德国牧羊犬(犬科犬属)。您一共有多少动物?您得把所有的绵羊、山羊和狗加起来,结果是7只。其实您刚刚应用了多态性,即为了计算,把三种不同种类的动物当成一种通用类型(“动物”)对待。如果您把绵羊、山羊和狗当成哺乳动物看待,这就是一个简单的信心飞跃。生物学家每天都以这种方式使用多态性,而程序员则以从其它科学领域“窃用”(我是指“重用”)好主意闻名。
Perl 完全支持
多态性
。但它用得不是很频繁,因为 Perl程序员看起来更喜欢用对象特性、而不是通过修改继承的行为来修改通用行为。这意味着您更可能看到创建三个 IO::Socket::INET 对象的代码:一个对象用于在端口 234 接收和发送 UDP 包、一个对象用于在端口 80 接收 TCP包,还有一个对象在端口 1024 发送 TCP 包,而不大会看到对第一种情况使用 IO::Socket::INET::UDPTransceiver 、对第二种情况使用 IO::Socket::INET::TCPReceiver 而对第三种情况使用 IO::Socket::TCPTransmitter 的代码。这就象是在生物学术语中说狗和山羊都是哺乳动物,但是山羊属于山羊属,而狗属于犬属。
OOP 纯化论者认为每件事都应该正确分类,但是 Perl 程序员根本不是纯化论者。他们往往更不拘束于 OOP规则,这使得他们在聚会中比 OOP 纯化论者更快乐。
封装
指的是以这样一种方式包含对象行为和特性:除非对象作者允许,否则用户无法访问该对象的行为和特性。在这种方式下,对象用户无法做不准他们做的事,无法访问不准他们访问的数据,并且通常是有害数据。Perl通常用松弛的方法封装。请参阅 。
为什么说 OOP 是一种强有力的方法?返回到我们最初的 OOP 如何是一种强有力的方法这一主题,我们现在可以看到 OOP结合了几个关键的概念,这使得它很难与过程型和函数型编程(PP 和 FP)混合使用。首先,PP 和 FP都没有继承或类多态性的概念,因为在 PP 和 FP 中根本就没有类。在 PP 和 FP中存在封装,但只在过程型级别,从来不作为类或对象属性封装。既然程序员不怕麻烦来使用这些基本的 OOP工具,那就意味着程序员通常更可能对整个项目使用 OOP,而不是混合不兼容的方法。
有人可能争论说所有程序最终都归结为指令的过程型执行,因此无论 OOP 程序实现得有多纯,每个 OOP 程序都在其函数(也称为方法)和创建第一个对象(该对象做其余工作)的代码中包含过程型代码。甚至象 Java 那样接近“纯”OOP 的语言都无法避免地需要一个 main() 函数。因此,看起来 OOP 只是 PP 的一个子集。但是这种 OOP 向序列指令的归结和实际为每个操作所执行的汇编程序指令一样,都不是系统架构设计师或程序员所关心的事。请记住,OOP 本身只是一种方法,而不是目的。
OOP 与过程型编程方法合作得不是很好,因为它集中在对象上,而过程型编程基于过程(我们将
过程
大致定义为不使用 OOP技术就可以得到的函数,而将
方法
定义为只有在对象中才能得到的函数)。正如方法一样,过程只是由用户调用的函数,但是二者之间有一些差异。
过程不使用对象数据。必须在它们的参数列表中为它们传递数据,或者它们必须使用所在作用域中的数据。过程可以访问调用它时传递给它的任何数据,甚至整个程序的全局数据。方法应该只访问它们对象的数据。实际上,方法的函数作用域通常是包含该方法的对象。
常常发现过程使用全局数据,尽管只有在绝对必要时才应该这样做。应该尽快重写使用全局数据的方法。过程通常用几个参数调用其它过程。方法应该只有几个参数,并且它们调用其它方法的次数比其它过程更多。
函数型编程(FP)与 OOP 配合不好有几个原因。最重要的原因是 FP 基于用来解决问题的详细函数型方法,而 OOP则使用对象来表达概念,并且,与 OOP 方法只能在包含它们的对象中使用不同,FP 过程得到处使用。
综上所述,我们现在可以解释 Perl 为什么是混合 OOP、FP 和 PP 方法的最佳语言之一。
Perl 是如何将 OOP 与过程型和函数型编程结合起来的?Perl 是一种松弛的语言。它极力让程序员以他们认为方便的任何方式做他们想做的任何事。这与 Java 和 C++之类的语言截然不同。例如,如果程序员原本没有声明变量,Perl乐于允许程序员自动创建变量(尽管不鼓励这样做,并且可以通过使用高度推荐的“usestrict”编译指示阻止)。如果您要向自己的脚开枪,Perl 会给您十发子弹和一个激光瞄准镜,然后站在一旁鼓励您。
因此,Perl是一种非常便于滥用方法的语言。别害怕。没关系。例如,访问内部的对象数据、实时更改类和实时重定义方法都是允许的。Perl方式是:允许程序员为了编码、调试和执行效率的目的而去打破规则。如果这有助于完成工作,那么没关系。因此,Perl本身可能是程序员最好的朋友,也可能是最坏的敌人。
如果混合 OOP、FP 和 PP 意味着打破规则,那么为什么任何人都想要混合 OOP、FP 和 PP 呢?让我们回头想想这个问题。什么是OOP、FP 和 PP?它们只是现有的为编程团队服务的编程方法、概念集和规则集。OOP、FP 和 PP是工具,每名程序员的首要工作就是要了解他的工具。如果一名程序员在排序散列时不能使用 FP 的 Schwartzian变换,而是编写他自己的 Sort::Hashtable ,或者不能重用 Sys::Hostname 模块,而是编写过程代码来获得系统主机名,那么这个程序员是在浪费时间、精力和金钱,并且降低了代码质量和可靠性。
一个编程团队可能会因为它们最熟知的工具而沾沾自喜,对它们来说,这可能正是最坏的事。如果一个团队只使用象计算机编程行业那样令人冲动和充满创新的行业中所保证的可用工具的一部分,那么它在几年之后注定要变得毫无用处。程序员应该能够结合任何使工作更有效、代码更好以及使团队更具创新能力的方法。Perl认可并鼓励这种态度。
OOP 的好处OOP的好处太多,本文难以列举。正如我在前面提到的那样,有很多关于该主题的书籍。这些好处中的一小部分是:易于代码重用、代码质量的改进、一致的接口和可适应性。
因为 OOP 建立在类和对象的基础之上,所以重用 OO 代码意味着在需要时只需简单地导入类。至今为止,代码重用是使用 OOP的唯一最主要原因,也是 OOP 在当今业界中的重要性和流行性日益增加的原因所在。
这里有一些陷阱。例如,在当前的情况下,以前问题的解决方案可能不理想,并且文档库编制得很差,以至于理解和使用文档编制很差的库所花的时间可能与重新编写库的时间一样长。系统架构设计师的工作是看到和避免这些陷阱。
使用 OOP可以提高代码质量,因为封装减少了数据毁坏(“友好之火”),而继承和多态性则减少了必须编写的新代码数量和复杂性。在代码质量和编程创新之间有一个微妙的平衡,这最好留给团队去发现,因为它完全取决于团队的构成和目的。
OOP 继承和重用使得在代码中实现一致的接口变得简单,但是并不能说所有的 OO代码都有一致的接口。程序员仍然必须遵循通用的体系结构。例如,团队应该在错误日志记录的格式和接口方面达成一致,最好通过一个允许日后扩展并且极其易用的示范模块接口来这样做。只有在那时,每名程序员才能承诺使用该接口,而不是无规则的print 语句,因为他们会认识到在出现下一个错误日志记录函数时,学习该接口的努力不会白费。
可适应性在编程中是一个有些含糊的概念。我愿意把它定义成对环境和用法更改的接受性和预见性。对于编写良好的软件来说,可适应性很重要,因为所有的软件必须随着外部世界而进化。编写良好的软件应该很容易进化。OOP通过模块设计、改进的代码质量和一致的接口确保新操作系统或者新报告格式不要求对体系结构的核心作出根本更改,从而有助于软件的进化。
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0