技术文章和通讯

介绍MATLAB中的面向对象编程

Stuart McGarrity和Adam Sifounakis, MathWorks


在创建软件应用程序时,将软件的各种构建块组织到相关的组中是很重要的。例如,自定义数值求解器可能需要几个配置参数和例程来执行完整的计算集。面向对象编程(OOP)允许您将求解器的配置参数(属性)及其函数(方法)组合成单个定义或。用户正确执行此求解器所需的一切都在该类中定义。

对象是类的实例。当程序执行时,对象根据其类定义创建,并按照类定义的方式进行行为。对象的属性表示它的状态,它的方法表示用户可能执行的所有操作。通过这种方式,代码作者可以很容易地对软件系统的所有相关数据和功能进行分组,用户也可以很容易地找到和使用代码作者开发的所有功能。

下面的示例使用面向对象编程构建一个应用程序,该应用程序将从传感器数组中分析传感器数据。

应用示例:分析传感器阵列数据

传感器阵列(图1)是传感器的集合,通常排列成一行,用于对雷达、声纳或蜂窝通信的空气、水或地面等介质进行采样。通过从空间的多个点收集时间样本,可以从被采样的介质中提取额外的信息。

图1所示。以未知角度探测两个远距离电磁源的传感器阵列。

我们的应用程序使用传感器阵列来确定多个远程电磁源(如无线电信标和雷达发射机)的到达方向(DOA)。在这种情况下,我们将尝试估计两个源相对于传感器阵列指向的方向的角度θ1和θ2。

检查数据项目和操作

对于这个应用程序,我们需要存储和表示以下数据:

  • 传感器和样品的数量
  • 采样传感器数据
  • 传感器采样率
  • 传感器间距
  • 远源波长
  • 波的速度
  • 传感器数据集名称或描述

我们将使用一种简单的基于快速傅里叶变换(FFT)的技术来估计源的DOA。该技术可以分解为多个部分,并作为操作集合实现。将实现少量实用程序操作,以帮助简化开发工作。例如,我们必须:

  • 从合成数据或获取的实时数据创建数据集
  • 检查和修改数据集值和参数
  • 绘制样本数据以帮助解释和验证
  • 计算和绘制数据集的功率谱(通过FFT方法的简单幅度平方)
  • 找出功率谱的峰值来估计源的DOA

确定了需要表示的数据和需要执行的活动之后,我们就可以用类属性表示数据,用类方法表示活动。

用类属性表示数据

我们首先定义一个类来描述传感器阵列。这个初始表示仅包含数据项,并将它们表示为类属性。

用类定义文件在MATLAB中定义一个类,该文件以classdef关键字,并由结束关键字。在类定义块中,附加的关键字块将描述类的不同方面,如类属性和类方法。图2所示的定义文件描述了一个类悲伤而已(传感器阵列数据集),我们需要在属性块中列出的所有数据项。

图2。类定义文件sads.m与属性。

创建对象并访问属性

要创建所定义类的对象或实例,可以使用该语句

>> s =;

要设置属性的值,我们可以指定它的名称,就像结构的字段一样

>> . numsensors = 16;

我们可以通过输入对象的名称来显示对象,查看所有可用的属性和当前值。

>> s s = sads with properties:波长:[]c: 300000000 NumSensors: 16 NumSamples: [] Data: [] Spacing: [] SampleRate: [] Name: []

所有的属性NumSensorsc仍然是空的。数据集现在可以被识别为悲伤而已对象使用函数,isa功能,命令,这在结构中是不可能的。

>> class(s) ans = 'sads'

对于创建代码来操作数据集的用户来说,识别变量类的能力非常重要,因为它允许他们确定要访问的可用数据项和可以合法执行的操作。

错误检查

如果使用结构来表示数据,则只需指定新字段名并为其赋值,就可以随时添加新字段名。当您在试验和原型化算法时,这个功能特别方便。但是,如果您拼错了字段名,则会静默地添加一个新字段,这可能会导致以后出现难以诊断的错误。

与结构不同,不能简单地通过指定新属性名并为其赋值来动态地向对象添加新属性。如果你拼错了一个对象属性名,MATLAB会立即发出一个错误。当对象被不像作者那样熟悉它的用户访问时,这种额外的错误检查级别是很有用的,这在大型应用程序开发期间是很常见的。

控制访问数据

类可以很好地控制属性访问。例如,它们允许您禁止修改属性、隐藏属性或使其动态计算。您可以通过在类定义文件中指定属性属性来控制对属性的访问。我们在图2中扩展类定义文件,将当前的属性列表划分为多个属性块,每个属性块都有惟一的属性属性:GetAccess常数,依赖(图3)。

图3。类定义文件sads.m与财产属性。

属性的值可以禁止修改属性常数属性。在我们的例子中,我们将设置光速属性c是常数。因为常量属性不会改变,所以可以通过引用类名来访问它们。

>> sads.c ans = 300000000

属性可以使属性只读SetAccess私有属性。属性的值可以使属性仅对操作它的方法可见GetAccess属性为private,就像我们将处理的波长财产。

您可以自由地更改私有属性的名称或特征,而不会影响对象的用户。这种定义软件的“黑盒”方法(称为封装)可以防止对象的用户依赖可能改变并破坏其代码的实现细节或特征。

通过设置其属性,指定仅在请求时计算属性依赖属性。

然后指定一个get方法,该方法在访问属性时自动调用。看到使用Get和Set方法访问属性章节中详细介绍了如何指定类方法。在我们的应用程序中,我们设置NumSensorsNumSamples要依赖的属性。

用类方法实现操作

方法或可在对象上执行的操作被指定为方法块中的函数列表。一个类可以包含多种类型的方法,每种方法实现不同的目的,每种方法的指定方式不同。下面的部分描述了许多这类方法。

将方法块添加到悲伤而已定义文件并将每个新方法添加到这个块中(图4)。

图4。类定义文件sads.m与方法,显示在MATLAB编辑器。为了便于查看,代码折叠特性用于隐藏大部分代码。

指定构造函数方法

在我们的示例中,我们将指定一个构造函数方法,该方法允许用户提供在创建对象时使用的参数。构造函数方法通常执行数据初始化和验证。对象现在是用

>> s = sads(数据,波长,采样率,间距,名称);

实现特定于应用程序的方法

我们将添加几个方法来实现在数据集上执行的特定于应用程序的操作。大多数方法将对象作为输入参数(例如,obj),并通过引用该变量来访问对象属性(例如,obj。NumSamples),如在以下方法中:

函数Mag = [mags,fflip] = magfft(obj, zpt) Mag = 0 (obj, zpt)NumSamples、zpt);...结束

虽然它需要额外的语法,但通过对象变量引用属性可以帮助将它们与局部函数变量区分开来,例如玛格以上。

调用方法

方法像函数一样被调用,对象作为参数传入。我们可以通过调用doa方法。

>> angle = doa(s) angle = -10.1642 18.9953

DOA角近似于图1所示的源的真实位置,分别为-10°和20°。

使用Get和Set方法访问属性

您可以通过指定相关的set和get方法来验证属性或实现相关属性。的get方法NumSensors财产。

函数NumSensors = get.NumSensors(obj)2)数据;结束

在访问属性时自动调用Get和set方法,例如使用

>> N = s.NumSensors;

使用重载指定已有MATLAB函数的方法

重载允许您通过在方法列表中提供具有该名称的函数来重新定义现有的MATLAB函数来处理对象。在我们的应用程序中,我们将包含一个重载的情节方法,提供了一个函数来可视化许多MATLAB用户所熟悉的数据集(图5)。

> >的情节(s)

图5。专用于传感器阵列数据集的重载绘图方法。

这个定制的绘图方法以最适合该数据集的方式表示信息,并用所有可用信息对其进行注释。它只在定义了它的对象上执行——这是一种比操纵路径中的目录顺序更健壮的方法。

如果您想为类提供专门的行为,还可以通过使用具有特殊名称的方法重载基本操作符甚至索引。

进一步开发应用程序

我们在本例中创建的类表示传感器阵列数据集,并允许我们轻松地对数据执行复杂的专门分析,包括主要的测向操作。我们可以使用这个类来快速评估基于fft的技术在不同场景下的性能。

我们可以使用其他的OO技术扩展应用程序。例如,我们可以这样做:

  • 使用继承定义现有类的子类(重用更广泛类别的定义来定义更具体的子类)
  • 指定静态方法,让我们可以为整个类定义一个操作
  • 使用带有引用行为的句柄类,使我们能够制作像链表这样的数据结构或在不复制大数据集的情况下处理它
  • 定义事件和监听器,让我们监视对象属性或动作

这些技术通过使我们能够进一步定义应用程序中的关系和行为,增强了我们管理复杂性的能力。

因为它是使用OO技术构建的,所以应用程序现在已经足够健壮,可以供其他人使用和维护,并且可以与整个组织中的其他应用程序集成。

2020年出版的

查看相关功能的文章

查看相关行业的文章