面向对象编程入门

面向对象编程的种子可以追溯到API(应用程序编程接口)的概念。API基本上是一张纸,它定义了一组子例程以及应用程序在调用它们时期望得到的行为。例如,图形API可能包括DrawLine(a,b)和DrawCircle(x,y,radius)这样的函数。

通过艾尔•奇泽姆 二四年二月一日
一目了然
  • 从api到对象

  • 模块化的优势

  • 糟糕的编码问题

  • 明确“类”和“实例”

栏:
获取NewGraphics API代码
关于类和实例的问题
简单地说,面向对象编程

面向对象编程的种子可以追溯到API(应用程序编程接口)的概念。API基本上是一张纸,它定义了一组子例程以及应用程序在调用它们时期望得到的行为。

例如,图形API可能包括DrawLine(a,b)和DrawCircle(x,y,radius)这样的函数。应用程序可以调用DrawCircle并期望在屏幕上看到一个圆圈。这可能是一个问题,因为不同的图形硬件供应商可以提供相同的API。Intel, Matrox, nVidia等都可以提供一个可以被任何应用程序使用的DrawCircle函数,即使硬件的内部设计和实现DrawCircle函数的实际代码完全不同。您所需要做的就是确保系统上安装的提供图形API的软件模块与系统上安装的硬件相匹配。您可以稍后安装更新、更强大的硬件(以及更新的软件),旧的图形应用程序将正常工作。

那么我们如何从这个过渡到面向对象编程呢?

api的缺点是你只能拥有其中的一种。如果你有一台有两个图形显示器的电脑呢?您不能按原样使用上面的API,因为它不允许您选择使用哪种显示,并且您不能安装两个API库,因为函数具有相同的名称,并且您无法指定调用这两个API库中的哪一个。解决这个问题的各种技术解决方案包括向API中的每个函数添加一个“适配器号”。相反,假设我们发明了一个名为GetNewGraphicsAPI()的系统函数,它将向我们返回一个指向定义良好的函数列表的指针,例如上面描述的API。假设我们在API中添加了一个名为SelectGraphicsAdaptor(…)的函数。我们可以像“GetNewGraphics API code”边栏中那样编写代码。

我们可以使用两个指针g1和g2在两个图形适配器上执行独立的操作。现在,不要考虑“指向函数列表的指针”,这是在普通的“C”编程中经常使用的一种常见(如果有点复杂)技术,而是考虑“对象”。事实上,c++对象是作为指向函数列表的指针在内部实现的。我们没有调用系统函数GetNewGraphicsAPI,而是稍微调整了一下语法,写成:

g1 = new GraphicsAPI();

在本例中,“new”是c++使用的一个新动词,它告诉系统获取我命名的模块/对象的新副本,在本例中为GraphicsAPI。

类与实例

您将听到几个与面向对象编程相关的常见术语。最常见和最令人困惑的是对象,实例.Class和Instance的定义很好,但Object的定义不太好。对象既可以引用类,也可以引用实例。您需要考虑上下文,以确定如何在特定情况下使用它。

考虑一个文件。您可能熟悉文件的概念。例如,您可能要处理一个轮班报告文件。您知道每个shift都会创建一个新的文件,您也知道文件中数据的格式,每个shift都会有不同的格式。如果有人问,“轮班报告文件是否存在?”您可以很轻松地回答,“这取决于是否运行了创建移位报告文件的程序。”

Class是可以创建的对象的定义(与创建shift报告的方式相同)。暂时回到旧的API编程风格,它包括一些类似于API提供的头文件的内容,这些头文件定义了API的函数。不同之处在于术语类还包括代码,在API的情况下,代码通常是作为软件库提供的。

请注意,创建报表文件的代码与您是否实际创建了报表文件无关。类似地,代码(实现对象的函数,如GraphicsAPI)和头文件(定义该代码中的函数)都存在,与是否创建了GraphicsAPI对象的实际副本无关。

这就引出了“实例”这个术语。实例只不过是对象的真实副本。只要您说打开/写入/关闭,您就有了一个真正的报告文件(除了系统中已经设计用于处理报告文件的所有代码之外)。只要你说“new”,你就有了一个真正的对象(除了所有设计用来处理与该对象相关的函数的代码)。

有关类和实例的更多信息,请参见侧栏“关于类和实例要考虑的问题”。

模块化的优势

简而言之,使用对象的好处是创建更快、更好、更便宜的代码(至少在做得好的情况下)。

正如定义良好的api是对图形函数进行硬编码的一大进步,对象也是对api的一大进步。它们允许代码更加模块化,并允许对这些模块进行更清晰和简洁的定义。这意味着代码可以更快地编写,错误更少,测试更容易。这意味着可以更容易地将新功能添加到系统中,并且通常可以在不更改底层系统代码的情况下完成。这意味着通常更容易为系统创建自定义接口和组件,因为接口定义得更清楚。

为什么?可扩展性、建模面向对象技术至少可以在三个层次上应用于过程控制。

首先,供应商可以并且应该使用它来构建他们的系统。如上所述,这将产生更快速完成的系统,更可靠,更容易修改和增强,并且更容易定制。

其次,它可以应用于脚本语言(如Visual Basic for Applications)通常提供的内置可扩展性。这允许系统集成商或最终用户使用面向对象的技术在应用程序级对系统进行编程。特别是,可以创建和重用系统对象,例如图形控件(编辑框、滑块等),以及这些对象的集合(对话框、控制器面板和定制的趋势显示)。此外,第三方图形控件(如ActiveX控件)可以稍后安装到系统上,然后添加到应用程序和显示中,而无需实际修改原始系统软件。这就像在你的个人电脑上安装和使用一个新的硬件,而不需要重新安装微软的Windows。这种外接控件可以用来更容易和灵活地使系统适应用户特定的需求。它们为系统集成商提供了优势,允许他们将基本供应商的系统应用于更广泛的应用,并为操作员和过程工程师创建更好的适合(即更有效的环境)。

最后,面向对象的技术可以合并到供应商提供的“流程模型”工具中。通常,至少对于日常操作显示而言,过程控制数据库和显示的体系结构与实际系统的体系结构匹配程度越高,系统就越容易创建、维护和使用。先进的控制和HMI系统允许最终用户使用拖放技术将各种简单的输入和输出(模拟和数字信号)聚合到更复杂的对象中,这些对象表示实际的过程对象,如阀门和泵。这些对象可以依次组合起来创建更高级别的对象,例如锅炉、搅拌器或烘干机。更高级的对象可以组合起来创建一条线、建筑物、工厂站点,甚至整个企业。

缺点:很难修复糟糕的代码

像任何其他形式的代码一样,面向对象的代码也可能做得很糟糕。事实上,糟糕的面向对象代码通常比糟糕的常规代码糟糕得多。如果做得不好,就更难理解,也更难修复。要做好它,需要比传统代码更多的训练、更多的知识、更多的实践,可能还需要更多的天生能力(智力)。这意味着,从比例上看,世界上糟糕的目标代码的百分比可能高于糟糕的常规代码的百分比。

面向对象的过程控制系统通常使用拖放操作,从而生成整个系统定义的图形表示。这样的系统在贸易展示中看起来绝对很棒。然而,图形数据库表示在实践中很难导航和维护;特别是对于大型系统。一个经过深思熟虑的分层组织可能会有所帮助,但仍然很难设计和维护。例如,不同页面上不同层和对象之间的连接可能难以用图形方式表示和处理。好的系统会在内部以某种相当标准的格式存储数据,可能是关系数据库,或者至少是XML文件;它们还允许您以图形方式或使用表和查询来处理数据。

作者信息
Al Chisholm是Intellution公司的联合创始人,也是OPC数据访问和OPC报警规范的原始架构师。他目前参与了MediaCaster公司的创业,该公司的目标是水和天然气行业的远程监控市场。

获取NewGraphics API代码

g1 = GetNewGraphicsAPI();

g2 = GetNewGraphicsAPI();

g1 - >;SelectGraphicsAdaptor(“英特尔”);

g2 - >;SelectGraphicsAdaptor(英伟达);

g1 - >; DrawCircle (50 50 25);

25 g2 - >; DrawCircle (100100);

关于类和实例的问题

通常很难解释Class和Instance之间的区别,特别是在高级图形拖放系统中。需要考虑的问题包括以下内容。

如果我以图形方式将几个阀门和传感器分组来定义一个锅炉,那么我是定义了一个通用的可重复使用的锅炉,还是简单地为一个具有特定阀门和传感器集的特定锅炉定义/分组I/O点?

如果我将该对象拖放到其他地方,它是一个新的锅炉,还是旧锅炉的第二个副本,并链接到所有相同的输入和输出?

如果我必须进入并更改连接和标记名称,以逻辑地将这个东西连接到我的物理Boiler #2,我如何知道要更改哪些内容?

我怎么知道我是否忘记了什么东西?

如果我改变了我常用的可重用“锅炉”定义,会发生什么?

我已经使用它的所有现有位置是否都以相同的方式更改,还是只有我在未来拖放的锅炉包含我所做的更改?

如果我的一个锅炉与其他锅炉有轻微的物理差异,这是很常见的?

我可以在不影响其他物理硬件的情况下调整与该物理硬件相关的“boiler”实例吗?

简单地说,面向对象编程

面向对象技术比传统编程技术更复杂,也更难掌握。

如果使用得当,面向对象技术可以更容易地创建软件,并使软件更加可靠和灵活。

面向对象技术可以应用于流程控制的所有级别,从供应商的本机代码到提供给用户/集成商的脚本,再到实际流程数据库和显示的组织和维护。

面向对象技术本身并不能保证更好的结果。仔细选择供应商,彻底测试系统,并确保您了解系统在实际应用程序中的工作情况。