Main Content

为属性实现 set/get 接口

标准 set/get 接口

一些 MATLAB® 对象(如图形对象)实现基于 setget 函数的接口。这些函数支持在单个函数调用中访问对象数组的多个属性。

您可以通过从以下类之一派生,将 setget 功能添加到您的类中:

  • matlab.mixin.SetGet - 当您要支持不区分大小写的属性名称部分匹配时使用。即使属性派生自 matlab.mixin.SetGet,使用圆点表示法引用属性时,仍需提供确切的属性名称。

  • matlab.mixin.SetGetExactNames - 当您只想支持区分大小写的属性名称完全匹配时使用。

注意

本节中提到的 setget 方法不同于属性的 set 和 get 访问方法。有关属性访问方法的信息,请参阅属性 get 和 set 方法

子类语法

使用抽象类 matlab.mixin.SetGetmatlab.mixin.SetGetExactNames 作为超类:

classdef MyClass < matlab.mixin.SetGet
   ...
end

由于 matlab.mixin.SetGetmatlab.mixin.SetGetExactNames 派生自 handle 类,因此您的子类也是 handle 类。

get 方法语法

get 方法使用对象句柄和属性名称返回对象属性值。例如,假设 H 是对象的句柄:

v = get(H,'PropertyName');

如果您指定一个属性名称和一个句柄数组,get 会以值的元胞数组形式返回每个对象的属性值:

CV = get(H,'PropertyName');

无论 H 的形状如何,CV 数组始终是一列。

如果指定一个属性名称的 char 向量元胞数组和一个句柄数组,get 将返回属性值的元胞数组。元胞中的每行对应于句柄数组中的一个对象。元胞中的每列都对应一个属性名称。

props = {'PropertyName1','PropertyName2'};
CV = get(H,props);

get 返回 m×n 元胞数组,其中 m = length(H)n = length(props)

如果指定句柄数组,但未指定属性名称,则 get 将返回 struct 类型的数组,数组中的每个结构体对应于 H 中的一个对象。每个结构体中的每个字段对应于由 H 的类定义的一个属性。每个字段的值就是对应属性的值。

SV = get(H);

如果不指定输出变量,则 H 必须为标量。

有关示例,请参阅对句柄数组使用 get

set 方法语法

set 方法为具有句柄 H 的对象的指定属性赋予指定值。如果 H 是句柄数组,MATLAB 会为数组 H 中每个对象的属性赋值。

set(H,'PropertyName',PropertyValue)

您可以将属性名称的元胞数组和属性值的元胞数组传递给 set

props = {'PropertyName1','PropertyName2'};
vals = {Property1Value,Property2Value};
set(H,props,vals)

如果 length(H) 大于 1,属性值元胞数组 (vals) 可以为每个对象中的每个属性设置值。例如,假设 length(H) 是 2(两个对象句柄)。您要为每个对象赋予两个属性值:

props = {'PropertyName1','PropertyName2'};
vals = {Property11Value,Property12Value;Property21Value,Property22Value};
set(H,props,vals))

上述语句等效于以下两个语句:

set(H(1),'PropertyName1',Property11Value,'PropertyName2',Property12Value)
set(H(2),'PropertyName1',Property21Value,'PropertyName2',Property22Value)

如果指定标量句柄,但没有属性名称,则 set 将返回 structH 的类中的每个属性都对应该结构体中的一个字段。每个字段包含一个空元胞数组。

SV = set(h);

提示

可以在一次 set 调用中使用属性名称/属性值元胞数组、结构体数组(字段名称作为属性名称,字段值作为属性值)和元胞数组的任意组合。

派生自 matlab.mixin.SetGet 的类

此示例类定义一个 set/get 接口,并演示继承的方法的行为:

classdef LineType < matlab.mixin.SetGet
   properties
      Style = '-'
      Marker = 'o'
   end
   properties (SetAccess = protected)
      Units = 'points'
   end
   methods
      function obj = LineType(s,m)
         if nargin > 0
            obj.Style = s;
            obj.Marker = m;
         end
      end
      function set.Style(obj,val)
         if ~(strcmpi(val,'-') ||...
               strcmpi(val,'--') ||...
               strcmpi(val,'..'))
            error('Invalid line style ')
         end
         obj.Style = val;
      end
      function set.Marker(obj,val)
         if ~isstrprop(val,'graphic')
            error('Marker must be a visible character')
         end
         obj.Marker = val;
      end
   end
end

创建类的实例并保存其句柄:

h = LineType('--','*');

使用继承的 get 方法查询对象属性的值:

get(h,'Marker')
ans =

'*'

使用继承的 set 方法设置属性的值:

set(h,'Marker','Q')

用 set 和 get 调用属性访问方法

使用 setget 方法时,MATLAB 会调用属性访问方法(LineType 类中的 set.Styleset.Marker)。

set(h,'Style','-.-')
Error using LineType/set.Style (line 20)
Invalid line style

有关属性访问方法的详细信息,请参阅 属性 get 和 set 方法

列出所有属性

使用 get 返回包含对象属性及其当前值的 struct

h = LineType('--','*');
SV = get(h)
SV = 

  struct with fields:

     Style: '--'
    Marker: '*'
     Units: 'points'

使用 set 返回包含具有 public SetAccess 的属性的 struct

S = set(h)
S = 

  struct with fields:

     Style: {}
    Marker: {}

LineType 类使用 SetAccess = protected 定义 Units 属性。因此,S = set(h) 不为 S 中的 Units 创建字段。

set 无法返回具有非公共 set 访问权限的属性的可能值。

对句柄数组使用 get

假设您创建了一个 LineType 对象数组:

H = [LineType('..','z'),LineType('--','q')]
H = 

  1x2 LineType with properties:

    Style
    Marker
    Units

H 是句柄数组时,get 返回属性值的 (length(H)×1) 元胞数组:

CV = get(H,'Style')
CV =

  2×1 cell array

    {'..'}
    {'--'}

H 是句柄数组而您没有指定属性名称时,get 返回 struct 数组,其中的字段具有与属性名称对应的名称。当 H 不是标量时,将 get 的输出赋给变量。

SV = get(H)
SV = 

2x1 struct array with fields:
    Style
    Marker
    Units

SV 结构体数组的第二个数组元素中获取 Marker 属性的值:

SV(2).Marker
ans =

'q'

句柄、名称和值的数组

您可以将句柄数组、属性名称元胞数组和属性值元胞数组传递给 set。对于 H 中的每个对象,属性值元胞数组必须有一行与之对应的属性值。对于属性名称数组中的每个属性,上述每行都必须有一个与之对应的值:

H = [LineType('..','z'),LineType('--','q')];
set(H,{'Style','Marker'},{'..','o';'--','x'})

set 的此调用的结果是:

H(1)
ans = 

  LineType with properties:

     Style: '..'
    Marker: 'o'
     Units: 'points
H(2)
ans = 

  LineType with properties:

     Style: '--'
    Marker: 'x'
     Units: 'points'

自定义属性列表

通过在子类中重新定义以下方法,自定义属性列表的显示方式:

  • setdisp - 如果在调用 set 时只使用单个标量句柄输入且不带输出参量,set 会调用 setdisp 来确定如何显示属性列表。

  • getdisp - 如果在调用 get 时只使用单个标量句柄输入且不带输出参量,get 会调用 getdisp 来确定如何显示属性列表。

为属性名称的部分匹配设置优先级

matlab.mixin.SetGet 派生的类可以使用 PartialMatchPriority 属性特性为部分名称匹配指定相对优先级。当解析匹配多个属性名称的不完整且不区分大小写的文本字符串时,MATLAB 应用此属性。

当不精确的名称字符串不具有多义性时,继承的 setget 方法可以解析不精确的属性名称。当部分属性名称因与多个属性匹配而具有多义性时,PartialMatchPriority 属性值可以确定 MATLAB 与哪个属性匹配。

默认优先级等效于 PartialMatchPriority = 1。要降低属性的相对优先级,请将 PartialMatchPriority 设置为 2 或更大的正整数值。随着 PartialMatchPriority 值的增加,属性的优先权会降低。

例如,在此类中,Verbosity 属性的名称匹配优先级高于 Version 属性。

classdef MyClass < matlab.mixin.SetGet
    properties
        Verbosity
    end
    properties (PartialMatchPriority = 2)
        Version
    end
end

使用可能具有多义性的不精确名称 Ver 调用 set 方法会设置 Verbosity 属性,因为其相对优先级较高。如果不设置 PartialMatchPriority 属性,具有多义性的名称将导致错误。

a = MyClass;
set(a,"Ver",10)
disp(a)
 MyClass with properties:

    Verbosity: 10
      Version: []

相同的名称选择机制也适用于 get 方法。

v = get(a,"Ver")
v =

    10 

大小写和名称匹配

大小写不匹配的全名匹配优先于具有较高优先级属性的部分匹配。例如,此类定义优先级为 1(默认值)的 BaseLine 属性和优先级为 2(低于 1)的 Base 属性。

classdef MyClass < matlab.mixin.SetGet
    properties
        BaseLine
    end
    properties (PartialMatchPriority = 2)
        Base
    end
end

用字符串 base 调用 set 方法会设置 Base 属性。BaseLine 具有更高的优先级,但只是大小写不一样的全名匹配更优先。

a = MyClass;
set(a,"base",-2)
disp(a)
 MyClass with properties:

    BaseLine: []
        Base: -2

添加新属性时减少不兼容问题

您可以使用 PartialMatchPriority 属性来避免在添加新属性时引入代码不兼容问题。例如,以下类使 setget 方法能够使用字符串 Dis 引用 Distance 属性,因为 DiscreteSamples 属性的优先级较低。

classdef Planet < matlab.mixin.SetGet
% Version 1.0
    properties
        Distance
    end
    properties(PartialMatchPriority = 2)
        DiscreteSamples
    end
end

该类的 2.0 版引入了名为 Discontinuities 的属性。为了防止在现有代码中导致具有多义性的部分属性名称,请使用 PartialMatchPriorityDiscontinuities 的优先级设置为低于以前存在的属性的优先级。

classdef Planet < matlab.mixin.SetGet
% Version 2.0
    properties
        Diameter;
        NumMoons = 0
        ApparentMagnitude;
        DistanceFromSun;
    end
    properties(PartialMatchPriority = 2)
        DiscreteSamples;
    end
    properties(PartialMatchPriority = 3)
        Discontinuities = false;
    end
end

对于 Planet 类的 1.0 版,对 set 方法的以下调用并不具有多义性。

p = Planet;
set(p,"Disc",true)

然而,随着 Discontinuities 属性的引入,字符串 Disc 将具有多义性。通过降低 Discontinuities 属性的优先级,字符串 Disc 将继续匹配 DiscreteSamples 属性。

注意

在编写可重用代码时,使用完整的、区分大小写的属性名称可以避免多义性,防止与后续软件版本不兼容,并生成更可读的代码。

另请参阅

| | |

相关主题