Main Content

验证属性值

类定义中的属性验证

MATLAB® 属性验证使您能够对属性值进行特定限制。您可以使用验证来约束属性值的类和大小。此外,您可以使用函数来建立属性值必须符合的条件。MATLAB 定义了一组验证函数,您也可以编写自己的验证函数。

在类定义中,属性验证的使用是可选的。

关于属性验证的其他信息

有关属性验证的详细信息,请参阅Property Class and Size Validation属性验证函数Metadata Interface to Property Validation

验证语法

下面代码中突出显示的区域显示属性验证的语法。

Properties block with validation syntax

属性验证包括以下任一项:

  • 大小 - 每个维度的长度,指定为正整数或冒号。冒号表示该维度中允许任何长度。赋给属性的值必须符合指定的大小或与指定的大小兼容。有关详细信息,请参阅Property Size Validation

  • 类 - 单个 MATLAB 类的名称。赋给属性的值必须属于指定的类或可转换为指定的类。使用 MATLAB 类或 MATLAB 支持的任何外部定义的类,但 Java® 和 COM 类除外。有关详细信息,请参阅Property Class Validation

  • 函数 - 以逗号分隔的验证函数名称列表。MATLAB 在应用任何可能的类和大小转换后,将赋给属性的值传递给每个验证函数。如果验证失败,验证器函数会引发错误,但不会返回值。有关详细信息,请参阅属性验证函数

    有关 MATLAB 验证函数的列表,请参阅属性验证函数

使用属性验证

使用公共属性的属性验证来控制用户代码赋给属性的值。

如果要将属性值限制为一组固定的标识符,请创建包含这些标识符的枚举类,并将属性值范围限制为该类。有关枚举类的信息,请参阅定义枚举类

MATLAB 类型转换规则适用于属性验证。例如,MATLAB 可以对数值类型进行强制转换。因此,将属性值限制为特定的数值类型(如双精度)不会阻止使用其他数值类型对属性赋值。

要确保只能将特定类型的值赋给属性,请将属性限制为仅支持所需类型转换的类型,或者使用验证函数指定属性允许的确切类,而不是指定属性类型。MATLAB 在执行任何验证函数之前先计算类型设定。有关详细信息,请参阅验证的顺序

指定有效默认值

确保赋给属性的默认值满足指定验证所施加的限制。如果未指定默认值,MATLAB 会使用指定类的空对象进行赋值来创建默认值;如果大小限制不允许使用空默认值,则调用默认构造函数来创建默认值。默认构造函数必须返回正确大小的对象。

使用属性验证的示例类

ValidateProps 类定义三个属性并进行验证。

classdef ValidateProps
   properties
      Location(1,3) double {mustBeReal, mustBeFinite}
      Label(1,1) string {mustBeMember(Label,["High","Medium","Low"])} = "Low"
      State(1,1) matlab.lang.OnOffSwitchState
   end
end
  • Location 必须为 double 类的 1×3 数组,其值是有限实数。

  • Label 必须为 string 标量,包含 "High""Medium""Low" 之一。

  • State 必须为 matlab.lang.OnOffSwitchState 类的枚举成员(offon)。

实例化时的验证

创建 ValidateProps 类的对象会对隐式和显式默认值执行验证:

a = ValidateProps
a = 

  ValidateProps with properties:

    Location: [0 0 0]
       Label: "Low"
       State: off

在创建对象时,MATLAB 会:

  • Location 属性值初始化为 [0 0 0],以满足大小和类要求。

  • Label 属性设置为默认值 "Low"。默认值必须为允许的值集的成员。空的 string 默认值会导致错误。

  • State 属性设置为 matlab.lang.OnOffSwitchState 类定义的 off 枚举成员。

有关 MATLAB 如何选择默认值的信息,请参阅Default Values Per Size and Class

验证的顺序

对属性赋值(包括类定义中指定的默认值)时,MATLAB 会按以下顺序执行验证:

  • 类验证 - 此验证可导致转换为不同类,例如将 char 转换为 string。属性赋值遵循 MATLAB 对数组的转换规则。

  • 大小验证 - 此验证可导致大小转换,例如标量扩展或列向量到行向量的转换。对指定大小验证的属性进行赋值时,其行为与 MATLAB 数组的赋值行为相同。有关索引赋值的信息,请参阅数组索引

  • 验证器函数 - MATLAB 按照从左到右的顺序将类验证和大小验证的结果传递给每个验证函数。在调用完所有验证函数之前可能会发生错误,从而结束验证过程。

  • set 方法 - MATLAB 在调用属性 set 方法(如果为属性定义了该方法)之前执行属性验证。通过属性 set 或 get 方法为属性赋值时不会再次应用验证。通常,您可以使用属性验证来替换属性 set 方法。

属性验证错误

ValueProp 类使用大小、类和函数验证来确保对 Value 属性的赋值是非负的双精度标量。

classdef ValueProp
   properties
      Value(1,1) double {mustBeNonnegative} = 0
   end
end

以下语句尝试将元胞数组赋给属性。此赋值违反类验证。

a.Value = {10,20};
Error setting property 'Value' of class 'ValueProp':
Invalid data type. Value must be double or be convertible to double.

以下语句尝试将 1×2 双精度数组赋给属性。此赋值违反大小验证。

a.Value = [10 20];
Error setting property 'Value' of class 'ValueProp':
Size of value must be scalar.

以下语句尝试将双精度标量赋给属性。此赋值未通过函数验证,该验证要求使用非负数。

a.Value = -10;
Error setting property 'Value' of class 'ValueProp':
Value must be nonnegative.

验证过程在遇到第一个错误时结束。

抽象属性验证

您可以为抽象属性定义属性验证。验证会应用于实现该属性的所有子类。但是,子类无法对其自身属性的实现使用任何验证。从多个类继承属性验证时,只有一个超类中的单一 Abstract 属性可以定义验证。任何超类都不能将属性定义为具体属性。

更改验证时不更新对象

如果在类的对象存在时更改属性验证,MATLAB 不会尝试将新验证应用于现有属性值。只有在您对现有对象的属性进行赋值时,MATLAB 才会应用新验证。

加载操作期间的验证

将对象保存到 MAT 文件时,MATLAB 会将所有非默认属性值与对象一起保存。在加载对象时,MATLAB 会在新创建的对象中还原这些属性值。

如果类定义更改了属性验证,使得加载的属性值不再有效,则 MATLAB 会将其值替换为当前定义的该属性的默认值。但是,在将当前类定义的默认值赋给属性之前,load 函数会阻止验证错误的显示。因此,在加载操作期间,验证错误会以静默方式被忽略。

为了说明此行为,以下示例创建、保存并加载了 MonthTemp 类的一个对象。此类将 AveTemp 属性限制为元胞数组。

classdef MonthTemp
   properties
      AveTemp cell 
   end
end

创建一个 MonthTemp 对象,并为 AveTemp 属性赋值。

a = MonthTemp;
a.AveTemp = {'May',70};

使用 save 保存对象。

save TemperatureFile a

编辑属性定义,以将 AveTemp 属性的验证类从元胞数组更改为 containers.Map

classdef MonthTemp
   properties
      AveTemp containers.Map
   end
end

在 MATLAB 路径上加载具有新类定义的已保存对象。MATLAB 无法将保存的值赋给 AveTemp 属性,因为元胞数组 {'May',70} 与当前要求属性值为 containers.Map 的对象不兼容。MATLAB 无法将元胞数组转换为 containers.Map

为了解决不兼容问题,MATLAB 将所加载对象的 AveTemp 属性设置为当前默认值,即空的 containers.Map 对象。

load TemperatureFile a
 a.AveTemp

ans = 

  Map with properties:

        Count: 0
      KeyType: char
    ValueType: any

现在系统为所加载对象的 AveTemp 属性赋了一个不同的值,因为保存的值现在无效。但是,加载过程会抑制验证错误的显示。

为了防止在更改类定义和重新加载对象时缺失数据,请实现 loadobj 方法或类转换器方法,使保存的值满足当前属性验证。

有关保存和加载对象的详细信息,请参阅对象的保存和加载过程

相关主题