用类表示结构化数据
将对象作为数据结构体
以下示例定义用于存储具有特定结构的数据的类。使用一致的结构存储数据,从而更轻松地创建函数来操作数据。MATLAB® struct
可以包含说明特定数据元素的字段名称,这是一种有用的数据组织方式。但是,类可以定义数据存储(属性)和对该数据执行的操作(方法)。本示例说明了这些优点。
示例背景
对于本示例,数据表示拉伸应力/应变测量值。这些数据用于计算各种材料的弹性模数。简而言之,应力是施加在材料上的力,应变是由此产生的形变。其比率决定材料的特性。虽然这种方法是一个大大简化了的流程,但足以满足本示例的目的。
数据的结构
下表说明了数据的结构。
数据 | 描述 |
---|---|
|
|
| 测试样本的编号 |
| 表示测试过程中施加给样本的应力的数值向量。 |
| 表示所施加应力对应值处应变的数值向量。 |
| 定义在测材料弹性模数的数值,该数值由应力和应变数据计算得出 |
TensileData
类
以下示例从类的简单实现开始,并以此实现为基础来说明特性如何增强类的有用性。
该类的第一个版本仅提供数据存储。该类为每个必需的数据元素定义一个属性。
classdef TensileData properties Material SampleNumber Stress Strain Modulus end end
创建实例并赋给数据
以下语句将创建一个 TensileData
对象,并为其进行数据赋值:
td = TensileData;
td.Material = 'Carbon Steel';
td.SampleNumber = 001;
td.Stress = [2e4 4e4 6e4 8e4];
td.Strain = [.12 .20 .31 .40];
td.Modulus = mean(td.Stress./td.Strain);
类相对于结构体的优势
像处理任何 MATLAB 结构体一样处理 TensileData
对象(在以前的语句中为 td
)。但是,相对于使用通用数据结构(例如 MATLAB struct
),将特化数据结构体定义为类具有以下优势:
将属性限制为特定值
可以通过定义属性 set 访问方法,将属性限制为特定值。MATLAB 每次设置属性值时都会调用 set 访问方法。
Material 属性 set 函数
Material
属性 set 方法将属性的赋值限制为以下字符串之一:aluminum
、stainless steel
或 carbon steel
。
将此函数定义添加到方法代码块中。
classdef TensileData properties Material SampleNumber Stress Strain Modulus end methods function obj = set.Material(obj,material) if (strcmpi(material,'aluminum') ||... strcmpi(material,'stainless steel') ||... strcmpi(material,'carbon steel')) obj.Material = material; else error('Invalid Material') end end end end
当尝试设置 Material
属性时,MATLAB 在设置属性值之前会调用 set.Material
方法。
如果该值与可接受值匹配,函数便将属性设置为该值。set 方法中的代码可以直接访问属性,以避免递归调用属性 set 方法。
例如:
td = TensileData;
td.Material = 'brass';
Error using TensileData/set.Material Invalid Material
用构造函数简化接口
通过添加一个构造函数来简化与 TensileData
类的接口,该构造函数:
使您能够将数据作为参量传递给构造函数
为属性赋值
该构造函数是一个与类同名的方法。
methods function td = TensileData(material,samplenum,stress,strain) if nargin > 0 td.Material = material; td.SampleNumber = samplenum; td.Stress = stress; td.Strain = strain; end end end
使用以下语句创建一个完整填充了数据的 TensileData
对象:
td = TensileData('carbon steel',1,... [2e4 4e4 6e4 8e4],... [.12 .20 .31 .40]);
按需计算数据
如果某个属性的值取决于其他属性的值,请使用 Dependent
特性定义该属性。MATLAB 不存储从属属性的值。当访问从属属性时,将使用从属属性 get 方法来确定属性值。当显示对象属性或作为显式查询的结果时,可以进行访问。
计算模数
TensileData
对象不存储 Modulus
属性的值。构造函数没有 Modulus
属性值的输入参量。Modulus
的值:
根据
Stress
和Strain
属性的值计算得出在
Stress
或Strain
属性的值发生变化时也必定会改变
因此,最好仅在需要时计算 Modulus
属性的值。使用属性 get
访问方法计算 Modulus
的值。
Modulus 属性 get 方法
Modulus
属性取决于 Stress
和 Strain
,因此其 Dependent
特性为 true
。将 Modulus
属性放在单独的 properties
代码块中,并设置 Dependent
特性。
get.Modulus
方法计算并返回 Modulus
属性的值。
properties (Dependent)
Modulus
end
仅使用默认特性在 methods
代码块中定义属性 get 方法。
methods function modulus = get.Modulus(obj) ind = find(obj.Strain > 0); modulus = mean(obj.Stress(ind)./obj.Strain(ind)); end end
此方法在消除分母数据中的零后,计算应力与应变数据的平均比率。
查询属性时,MATLAB 会调用 get.Modulus
方法。例如,
td = TensileData('carbon steel',1,... [2e4 4e4 6e4 8e4],... [.12 .20 .31 .40]); td.Modulus
ans = 1.9005e+005
Modulus 属性 set 方法
要设置 Dependent
属性的值,该类必须实现属性 set 方法。不需要允许显式设置 Modulus
属性。但您可以使用 set 方法提供自定义的错误消息。Modulus
set 方法引用当前属性值,然后返回错误:
methods function obj = set.Modulus(obj,~) fprintf('%s%d\n','Modulus is: ',obj.Modulus) error('You cannot set the Modulus property'); end end
显示 TensileData
对象
TensileData
类重载 disp
方法。此方法控制命令行窗口中的对象显示。
disp
方法显示 Material
、SampleNumber
、Modulus
属性的值。它不显示 Stress
和 Strain
属性数据。这些属性包含在命令行窗口中不容易查看的原始数据。
disp
方法使用 fprintf
在命令行窗口中显示格式化的文本:
methods function disp(td) fprintf(1,... 'Material: %s\nSample Number: %g\nModulus: %1.5g\n',... td.Material,td.SampleNumber,td.Modulus); end end
绘制应力对应变的图的方法
查看应力/应变数据图有助于确定材料在所施加的拉力范围内的行为。TensileData
类会重载 MATLAB plot
函数。
plot
方法创建应力对应变数据的线性图,并添加标题和轴标签,从而生成一个拉力数据记录的标准化图:
methods function plot(td,varargin) plot(td.Strain,td.Stress,varargin{:}) title(['Stress/Strain plot for Sample',... num2str(td.SampleNumber)]) ylabel('Stress (psi)') xlabel('Strain %') end end
该方法的第一个参量是包含数据的 TensileData
对象。
该方法将参量的变量列表 (varargin
) 直接传递给内置 plot
函数。TensileData
plot
方法允许您传递线条设定符参量或属性名称-值对组。
例如:
td = TensileData('carbon steel',1,... [2e4 4e4 6e4 8e4],[.12 .20 .31 .40]); plot(td,'-+b','LineWidth',2)
TensileData
类概要
示例代码 | 讨论 |
---|---|
classdef TensileData | 值类支持对象的独立副本。有关详细信息,请参阅句柄类和值类的比较 |
properties
Material
SampleNumber
Stress
Strain
end
| 请参阅数据的结构 |
properties (Dependent)
Modulus
end | 查询时计算 有关一般信息,请参阅从属属性的 get 和 set 方法 |
methods | 有关方法的一般信息,请参阅Ordinary Methods |
function td = TensileData(material,samplenum,... stress,strain) if nargin > 0 td.Material = material; td.SampleNumber = samplenum; td.Stress = stress; td.Strain = strain; end end | 有关此代码的信息,请参阅用构造函数简化接口。 有关构造函数的一般信息,请参阅类构造函数方法 |
function obj = set.Material(obj,material) if (strcmpi(material,'aluminum') ||... strcmpi(material,'stainless steel') ||... strcmpi(material,'carbon steel')) obj.Material = material; else error('Invalid Material') end end | 限制 有关此代码的信息,请参阅将属性限制为特定值。 有关属性 set 方法的一般信息,请参阅属性 get 和 set 方法。 |
function m = get.Modulus(obj) ind = find(obj.Strain > 0); m = mean(obj.Stress(ind)./obj.Strain(ind)); end | 查询时计算 有关此代码的信息,请参阅Modulus 属性 get 方法。 有关属性 get 方法的一般信息,请参阅属性 get 和 set 方法。 |
function obj = set.Modulus(obj,~) fprintf('%s%d\n','Modulus is: ',obj.Modulus) error('You cannot set Modulus property'); end | 为 有关属性 set 方法的一般信息,请参阅属性 get 和 set 方法。 |
function disp(td) fprintf(1,'Material: %s\nSample Number: %g\nModulus: %1.5g\n',... td.Material,td.SampleNumber,td.Modulus) end | 重载 有关此代码的信息,请参阅显示 TensileData 对象 有关重载 disp 的一般信息,请参阅Overloading the disp Function |
function plot(td,varargin) plot(td.Strain,td.Stress,varargin{:}) title(['Stress/Strain plot for Sample',... num2str(td.SampleNumber)]) ylabel('Stress (psi)') xlabel('Strain %') end | 重载 |
end end |
|