定义类方法和函数

方法代码块

classdef 代码块内的 methods 代码块中将方法定义为 MATLAB® 函数。构造函数方法与类同名,并返回类的初始化对象。要创建具有该实例独有属性值的对象,请在类构造函数中为属性赋值。用 end 语句终止所有方法函数。

classdef ClassName
   properties
      PropertyName
   end
   methods
      function obj = ClassName(arg1,...)
         obj.PropertyName = arg1;
         ...
      end
      function ordinaryMethod(obj,arg1,...)
         ...
      end
   end
   methods (Static)
      function staticMethod(arg1,...)
         ...
      end
   end
end

方法调用语法

与 C++ 和 Java® 等语言不同的是,MATLAB 中没有传递给所有方法的特殊隐藏类对象。必须将类的对象显式传递给方法。最左边的参数不需要是类对象,参数列表可以有多个对象。MATLAB 调度由主导参数的类定义的方法。有关详细信息,请参阅方法调用

方法在被调用时必须位于 MATLAB 路径上。例如,如果创建一个对象,然后将当前文件夹更改为对方法文件不可见的文件夹,则调用该方法时会出错。

请在您的 MATLAB 代码中始终使用区分大小写的方法名称。

普通方法

使用 MATLAB 函数语法或圆点表示法调用普通方法。例如,假设您有一个定义 ordinaryMethod 的类。传递定义类的对象和任何需要的参数。

classdef MyClass
   methods
      function out = ordinaryMethod(obj,arg1)
      ...
      end
   end
end

使用类的对象 obj 和以下任一语法调用 ordinaryMethod

obj = MyClass;
r = ordinaryMethod(obj,arg1);
r = obj.ordinaryMethod(arg1);

静态方法

静态方法不需要类的对象。要调用静态方法,请在方法名称前加上类名,以便 MATLAB 确定哪个类定义该方法。

classdef MyClass
   methods (Static)
      function out = staticMethod(arg1)
      ...
      end
   end
end

使用语法 classname.methodname 调用 staticMethod

r = MyClass.staticMethod(arg1);

有关不需要其类对象的方法的信息,请参阅静态方法

私有方法

使用 Access 方法属性创建一个私有方法。您不需要使用私有文件夹。

有关方法属性的列表,请参阅方法特性

有关方法的更多详细信息

方法

类相关函数

您可以在包含类定义 (classdef) 的文件中定义不是类方法的函数。在 classdef - end 代码块之外但在与类定义相同的文件中定义局部函数。classdef 文件中定义的函数与局部函数类似。您可以从同一文件的任何位置调用这些函数,但是,它们在您用于定义它们的文件之外不可见。

classdef 文件中的局部函数对于仅在该文件中使用的工具函数非常有用。这些函数可以接受或返回类实例参数,但不会像普通方法中那样是必需的。例如,以下代码在 classdef 代码块之外定义 myUtilityFcn

classdef MyClass
   properties
      PropName
   end
   methods
      function obj = MyClass(arg1)
         obj.PropName = arg1;
      end 
   end 
end % End of classdef

function myUtilityFcn
   ...
end

您还可以创建包函数,这要求在调用这些函数时使用包名称。

如何重载函数和运算符

为您的类重载 MATLAB 函数,方法是定义一个与要重载的函数同名的类方法。在类实例中调用该函数时,MATLAB 会调度该类方法。

您可以通过用适当的名称定义类方法来重载 MATLAB 算术、逻辑、关系和索引运算符。

有关为该类定义的运算的列表,请参阅 handle 类。从 handle 派生的所有类都继承这些方法。

在单独的文件中定义方法的规则

以下规则适用于在单独的文件中定义的方法:

  • 要为在单独文件中定义的方法指定属性,请在 classdef 文件的方法代码块中声明此方法。使用方法代码块指定属性值。
  • 将方法代码块中声明的语法(如果使用)与方法的 function 行匹配。
  • 该单独文件必须位于类 (@) 文件夹中。
  • 类构造函数方法必须在 classdef 文件中定义。构造函数不能位于单独的文件中。
  • 必须在 classdef 文件中定义句柄类 delete 方法。delete 方法不能位于单独的文件中。

    所有在其名称中使用圆点的函数都必须在 classdef 文件中定义,包括:

    • 转换器方法,这些方法必须使用包名称作为类名的一部分,因为类包含在包中
    • 属性 set 和 get 访问方法

有关在单独的文件中定义方法的详细信息,请参阅在单独文件中定义方法

创建简单类

设计类

类的基本目的是定义封装数据的对象以及对该数据执行的操作。例如,BasicClass 定义一个属性和对该属性中的数据执行操作的两个方法:

  • Value - 此属性包含存储在类对象中的数值数据
  • roundOff - 此方法将属性值舍入到两位小数
  • multiplyBy - 此方法将属性值乘以指定数值

以下是 BasicClass 的定义:

classdef BasicClass
   properties
      Value {mustBeNumeric}
   end
   methods
      function r = roundOff(obj)
         r = round([obj.Value],2);
      end
      function r = multiplyBy(obj,n)
         r = [obj.Value] * n;
      end
   end
end

有关类语法的汇总,请参阅 classdef

要使用类,请执行以下操作:

  • 将类定义保存在与该类同名的 .m 文件中。
  • 创建该类的一个对象。
  • 访问属性以将数据赋给属性。
  • 调用方法以对这些数据执行操作。

创建对象

使用类名创建类的一个对象:

a = BasicClass
a = 

  BasicClass with properties:

    Value: []

属性值最初为空。

访问属性

使用对象变量加点加属性名称的方式为 Value 属性赋值:

a.Value = pi/3;

要返回属性值,请使用不带赋值的圆点表示法:

a.Value
ans =

    1.0472

有关类属性的信息,请参阅属性语法

调用方法

对对象 a 调用 roundOff 方法:

roundOff(a)
ans =

    1.0500

将对象作为第一个参数传递给接受多个参数的方法,此处以 multiplyBy 方法的调用为例:

multiplyBy(a,3)
ans =

    3.1416

您也可以使用圆点表示法来调用方法:

a.multiplyBy(3)

使用圆点表示法时,没有必要将对象作为参数显式传递。该表示法将对象置于方法名称左侧,用点隔开。

有关类方法的信息,请参阅定义类方法和函数

添加构造函数

类可以定义一个特殊的方法来创建类对象,称为构造函数。您可以使用构造函数方法将参数传递给构造函数,用以对属性赋值。BasicClassValue 属性使用 mustBeNumeric 函数限制其可能的值。

以下是 BasicClass 类的构造函数。如果在调用构造函数时带有输入参数,此参数会被赋给 Value 属性。如果在调用构造函数时不带输入参数,则 Value 属性采用其默认值,即空 ([])。

methods        
    function obj = BasicClass(val)
        if nargin == 1
            obj.Value = val;
        end
    end
end

通过将此构造函数添加到类定义中,只需一个步骤即可创建对象并设置属性值:

a = BasicClass(pi/3)
a = 

  BasicClass with properties:

    Value: 1.0472

构造函数还可以执行与创建类对象相关的其他操作。

有关构造函数的信息,请参阅类构造函数方法

方法向量化

MATLAB® 支持运算向量化。例如,您可以向向量添加数字:

[1 2 3] + 2
ans =

     3     4     5

MATLAB 将数字 2 添加到数组 [1 2 3] 中的每个元素。要向量化算术运算符方法,请将 obj.Value 属性引用括在方括号中。

[obj.Value] + 2

此语法使方法能够处理对象数组。例如,使用索引赋值创建一个对象数组。

obj(1) = BasicClass(2.7984);
obj(2) = BasicClass(sin(pi/3));
obj(3) = BasicClass(7);

则以下表达式:

[obj.Value] + 2

等效于以下表达式:

[obj(1).Value obj(2).Value obj(3).Value] + 2

由于 roundOff 方法是向量化的,因此它可以对数组执行运算:

roundOff(obj)
ans =

    2.8000    0.8700    7.0000

重载函数

类可以通过定义与现有 MATLAB 函数同名的方法来实现现有功能,例如加法。例如,假设您要添加两个 BasicClass 对象。这通常意味着将每个对象的 Value 属性的值相加。

下面是 MATLAB plus 函数的重载版本。它将 BasicClass 类的加法定义为属性值相加:

method
   function r = plus(o1,o2)
      r = [o1.Value] + [o2.Value];
   end
end

通过实现名为 plus 的方法,您可以对 BasicClass 的对象使用“+”运算符。

a = BasicClass(pi/3);
b = BasicClass(pi/4);
a + b
ans =

    1.8326

通过向量化 plus 方法,您可以对对象数组执行运算。

a = BasicClass(pi/3);
b = BasicClass(pi/4);
c = BasicClass(pi/2);
ar = [a b];
ar + c
ans =

    2.6180    2.3562

相关信息

有关重载函数的信息,请参阅在类定义中重载函数

有关重载运算符的信息,请参阅运算符重载

BasicClass 代码列表

以下是添加本主题中讨论的功能后的 BasicClass 定义:

classdef BasicClass
    properties
        Value {mustBeNumeric}
    end
    methods
        function obj = BasicClass(val)
            if nargin == 1
                obj.Value = val;
            end
        end
        function r = roundOff(obj)
            r = round([obj.Value],2);
        end
        function r = multiplyBy(obj,n)
            r = [obj.Value] * n;
        end
        function r = plus(o1,o2)
            r = [o1.Value] + [o2.Value];
        end
    end
end

子类定义语法

要定义作为另一个类的子类的类,请将超类添加到 classdef 行中的 < 字符后:

classdef ClassName < SuperClass

从多个类继承时,使用 & 字符来指示超类的组合:

classdef ClassName < SuperClass1 & SuperClass2

有关从多个超类派生的详细信息,请参阅Class Member Compatibility

类属性

子类不继承超类属性。

子类化 double

假设您要定义从 double 派生的类,并将值限制为正数。PositiveDouble 类:

classdef PositiveDouble < double
   methods
      function obj = PositiveDouble(data)
         if nargin == 0
            data = 1;
         else
            mustBePositive(data)
         end
         obj = obj@double(data);
      end
   end
end

使用 1×5 数值数组创建 PositiveDouble 类的对象:

a = PositiveDouble(1:5);

您可以像对任何双精度值一样对该类的对象执行运算。

sum(a)
ans =

    15

PositiveDouble 类的对象必须为正值。

a = PositiveDouble(0:5);
Error using mustBePositive (line 19)
Value must be positive.

Error in PositiveDouble (line 7)
            mustBePositive(data)

Subclassing Multiple Classes(继承多个类)

Specify Multiple Superclasses

When inheriting from multiple classes, use the & character to indicate the combination of the superclasses:

classdef ClassName < SuperClass1 & SuperClass2

For more information on class syntax, see Subclass Syntax.

Class Member Compatibility

When you create a subclass derived from multiple superclasses, the subclass inherits the properties, methods, and events defined by all specified superclasses. If more than one superclass defines a property, method, or event having the same name, there must be an unambiguous resolution to the multiple definitions. You cannot derive a subclass from any two or more classes that define incompatible class members.

Here are various situations where you can resolve name and definition conflicts.

Property Conflicts

If two or more superclasses define a property with the same name, then at least one of the following must be true:

  • All, or all but one of the properties must have their SetAccess and GetAccess attributes set to private
  • The properties have the same definition in all superclasses (for example, when all superclasses inherited the property from a common base class)

Method Conflicts

If two or more superclasses define methods with the same name, then at least one of the following must be true:

  • The method Access attribute is private so only the defining superclass can access the method.
  • The method has the same definition in all subclasses. This situation can occur when all superclasses inherit the method from a common base class and none of the superclasses override the inherited definition.
  • The subclass redefines the method to disambiguate the multiple definitions across all superclasses. Therefore, the superclass methods must not have their Sealed attribute set to true.
  • Only one superclass defines the method as Sealed, in which case, the subclass adopts the sealed method definition.
  • The superclasses define the methods as Abstract and rely on the subclass to define the method.

Event Conflicts

If two or more superclasses define events with the same name, then at least one of the following must be true:

  • The event ListenAccess and NotifyAccess attributes must be private.
  • The event has the same definition in all superclasses (for example, when all superclasses inherited the event from a common base class)

Multiple Inheritance

Resolving the potential conflicts involved when defining a subclass from multiple classes often reduces the value of this approach. For example, problems can arise when you enhance superclasses in future versions and introduce new conflicts.

Reduce potential problems by implementing only one unrestricted superclass. In all other superclasses, all methods are

  • Abstract
  • Defined by a subclass
  • Inherited from the unrestricted superclass

When using multiple inheritance, ensure that all superclasses remain free of conflicts in definition.

  • alipay_img
  • wechat_img
届ける言葉を今は育ててる
最后更新于 2023-05-11