Main Content

用类表示结构化数据

将对象作为数据结构体

以下示例定义用于存储具有特定结构的数据的类。使用一致的结构存储数据,从而更轻松地创建函数来操作数据。MATLAB® struct 可以包含说明特定数据元素的字段名称,这是一种有用的数据组织方式。但是,类可以定义数据存储(属性)和对该数据执行的操作(方法)。本示例说明了这些优点。

示例背景

对于本示例,数据表示拉伸应力/应变测量值。这些数据用于计算各种材料的弹性模数。简而言之,应力是施加在材料上的力,应变是由此产生的形变。其比率决定材料的特性。虽然这种方法是一个大大简化了的流程,但足以满足本示例的目的。

数据的结构

下表说明了数据的结构。

数据

描述

Material

char 标识被测材料的类型的向量

SampleNumber

测试样本的编号

Stress

表示测试过程中施加给样本的应力的数值向量。

Strain

表示所施加应力对应值处应变的数值向量。

Modulus

定义在测材料弹性模数的数值,该数值由应力和应变数据计算得出

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),将特化数据结构体定义为类具有以下优势:

  • 用户不小心拼错字段名称时会收到错误消息。例如,键入以下内容:

    td.Modulus = ...
    

    会直接在结构体中添加一个字段。但如果 tdTensileData 类的一个实例,则将返回错误。

  • 类易于重用。一旦定义了类,就可以轻松地使用添加新属性的子类来扩展它。

  • 类易于识别。类有名称,因此您可以使用 whosclass 函数与工作区浏览器来识别对象。使用类名,可以轻松地用有意义的名称来引用记录。

  • 赋值时,类可以验证各个字段值,包括类或值。

  • 类可以限制对字段的访问,例如,允许读取某个特定字段,但不能更改该字段。

将属性限制为特定值

可以通过定义属性 set 访问方法,将属性限制为特定值。MATLAB 每次设置属性值时都会调用 set 访问方法。

Material 属性 set 函数

Material 属性 set 方法将属性的赋值限制为以下字符串之一:aluminumstainless steelcarbon 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 的值:

  • 根据 StressStrain 属性的值计算得出

  • StressStrain 属性的值发生变化时也必定会改变

因此,最好仅在需要时计算 Modulus 属性的值。使用属性 get 访问方法计算 Modulus 的值。

Modulus 属性 get 方法

Modulus 属性取决于 StressStrain,因此其 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 方法显示 MaterialSampleNumberModulus 属性的值。它不显示 StressStrain 属性数据。这些属性包含在命令行窗口中不容易查看的原始数据。

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)

Stress graphed as function of strain

TensileData 类概要

示例代码讨论
classdef TensileData

值类支持对象的独立副本。有关详细信息,请参阅句柄类和值类的比较

   properties
      Material
      SampleNumber
      Stress
      Strain
   end

请参阅数据的结构

   properties (Dependent)
      Modulus
   end 

查询时计算 Modulus。有关此代码的信息,请参阅按需计算数据

有关一般信息,请参阅从属属性的 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

限制 Material 属性的可能值。

有关此代码的信息,请参阅将属性限制为特定值

有关属性 set 方法的一般信息,请参阅属性 get 和 set 方法

   function m = get.Modulus(obj)
      ind = find(obj.Strain > 0); 
      m = mean(obj.Stress(ind)./obj.Strain(ind)); 
   end 

查询时计算 Modulus 属性。

有关此代码的信息,请参阅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 

Dependent Modulus 属性添加 set 方法。有关此代码的信息,请参阅Modulus 属性 set 方法

有关属性 set 方法的一般信息,请参阅属性 get 和 set 方法

   function disp(td)
      fprintf(1,'Material: %s\nSample Number: %g\nModulus: %1.5g\n',...
      td.Material,td.SampleNumber,td.Modulus)
   end 

重载 disp 方法以显示特定属性。

有关此代码的信息,请参阅显示 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 

重载 plot 函数以接受 TensileData 对象和应力对应变的图。

绘制应力对应变的图的方法

   end
end

methodsclassdefend 语句。

 展开类代码

相关主题