本系列内容为《MATLAB面向对象编程–从入门到设计模式》学习笔记,特此说明。
Value类和Handle类
MATLAB面向对象编程中有两种类:一种叫叫做Value类(Value Class),即数值类;另一种叫做Handle 类(Handle Class),也叫句柄类或引用类。
两者区别:定义的类是否继承了MATLAB内部提供的一个Handle基类。
%Value 类
classdef SomeValue
properties
valValue
end
methods
function obj = SomeValue(N)
obj.valValue = N;
end
end
end
%Handle 类
classdef SomeHandle < handle %区别
properties
ValHandle
end
methods
function obj = SomeHandle(N)
obj.ValHandle = N;
end
end
Value类对象和Handle类对象区别
复制时区别
clear all;clc;
mValue = SomeValue(10);
mHandle = SomeHandle(10);
%复制
nValue = mValue;
nHandle mHandle;
MATLAB对于Value类对象在内存中做了完全的拷贝,也叫深拷贝。
而对于Handle类对象,MATLAB只复制Handle类对象本身,而没有复制句柄对象指向得到实际数据。Handle类对象的复制不是一个完全的复制,不是一个深拷贝(Deep Copy),而是一个浅拷贝(Shallow Copy),因为没有深入到Handle类所指向的数据对实际数据进行复制。
Value 类对象和Handle类对象当做函数参数时区别
对于Value类对象,参数的传递方式是:复制必要的信息到函数工作空间中,当MATLAB发现该函数对传入的参数进行了修改,并且该参数时Value类对象时,MATLAB就构造出一个局部拷贝。
Handle类对象,参数传递方式也是赋值局部对象,但在函数内部,函数修改的不是针对Handle 类对象所指向的数据,所以,MATLAB内部并不需要做额外的处理,并且该函数成功地修改了Handle类对象所指向的数据。
综上所述,Handle类对象可以用来在函数中修改传来的参数。
MATLAB对参数的处理方式:如果希望在函数体内修改参数,则需要传递Handle类对象;否则就要使用Value类,并且把修改完的对象当做结果返回。
使用Value类或Handle 类的情况
Value类较为适合比较简单的数据,其行为和MATLAB的普通变量、matrix、struct、cell基本一致,他们完全由其所含的数据值类定义。若不介意副本的存在,并且希望每次执行对象的复制时都可以得到一个独立的副本,则适合使用Value类。如果一个数据在其他多处都有副本,并且希望修改其中的副本时其他所有的副本都会受到影响,也被修改,则使用Handle类。
Handle类对象提供的是对实际数据的一个访问渠道,从实用计算的角度来说,如果数据体积比较大,并且希望这些数据在各个方法、函数之间传递迅捷,不需要被局部复制,则可以使用Handle类来包装该数据。
从物理的角度来看,如果类的对象对应一个具体的物理对象,比如一个串口、一个窗口等,应该将其设计成Handle类,因为对这些对象进行复制仅仅是访问他们的一个渠道。
从功能的角度来看,Value类没有提供任何内置的方法,而Handle基类提供了delete方法,可以定义events和addlistener方法等,使Handle类的功能更加强大。
从性能的角度来看,因为Handle 类对象其实是内部数据的一个全权代理,对Handle类属性的访问经历了一个中间层的代理,因此Handle 类对象属性的访问速度比Value类对象属性访问速度稍慢。
类的析构函数(Destructor)
对象的生存周期
在MATLAB中,不论对象还是普通变量,都占用内存,不需要时要释放占用的内存资源。
所谓对象的生存周期,是指对象从产生到释放的过程。
析构函数
析构函数在对象脱离其作用域或者被销毁时负责收尾工作,比如关闭文件句柄、释放数据所占的内存空间等。MATLAB规定,对执行这种任务的类方法要命名为delete.
无论是Value类还是Handle 类,如果在对象的清除过程中涉及释放其占用的系统资源,那么需要自己定义delete函数。
Value 类本身不存在默认的delete方法,所以如果不定义delete方法,那么就无法对其使用delete 方法。
Handle类需要继承一个Handle的基类,该基类中已经定义了一个delete方法,可以直接对Handle 类对象使用delete方法。对Handle 类对象使用delete将释放该Handle 所指向的数据。
MATLAB提供一个isvalid函数,用来检查Handle类对象是否有指向任何实际的数据。该函数对失效的Handle 类对象返回false。
需要自定义delete方法的情况
当类的对象占用了一些系统资源而无法自动释放时,需要自动重载一个delete 方法来释放这些系统资源。比如Value类或Handle类中,构造函数打开了一个文件句柄,则需要在delete 方法中关闭这个文件句柄。
%Value类
classdef AVal
properties
fid = fopen('file.txt');
end
methods
function delete(obj)
fclose(obj.fid);
end
end
end
%Handle类
classdef BVal < handle
properties
fid = fopen('file.txt');
end
methods
function delete(obj)
fclose(obj.fid);
end
end
end
对于普通的属性,MATLAB在销毁对象时会自动释放这些属性所占用的内存,而没有必要专门定义delete方法来删除对象中的某个属性。
Value类没有析构函数
对于Value类而言,Value类的delete 方法只是自定义的一个方法,不是MATLAB承认的合法析构函数,所以该函数的名字是可以任意命名的。这个方法的存在主要是提醒不要忘记释放资源,由于它的delete 方法不是析构函数,MATLAB不会自动调用,需要显式地调用它。
MATLAB会自动调用Handle类对象的析构函数
对于Handle类而言:MATLAB Handle基类已经提供了基本的delete方法的实现方法,如果有额外的需要,则必须在子类中重载这个delete方法。