Test Handle class
Let's say that the sensor array data set was very large, taking up several GB. Althought you may modfiy it and you would never need to make a copy of it. In this case a handle class implementation may be more appropriate
Contents
Class def
(see handleImp.sads) Looking at the class def we see it inherits from the built-in handle class. Let's look at how its behavior is different from a value class.
clear % we will clear the workspace clear import % clear import loadparameters % load in our parameters
Copy behavior
Let's look at the copying behavior.
Value Class
We will create an instance first of the value class we made which has value behavior.
v=valueImp.sads(Data, Wavelength,SampleRate,Spacing,Name); v.Name
ans = Sensor Array Amplitudes
If you copy a value classes all is contents are copied.
v1=v; % Make a copy the value object v1.Name='New Name'; % Change the name string property of new object v.Name % and the original name property is uneffected as you would expect
ans = Sensor Array Amplitudes
Handle Class
We will now create an instance of the handle class which has reference behavior. Hote how, by using packages, we can work with two classes with the same name.
h=handleImp.sads(Data, Wavelength,SampleRate,Spacing,Name); h.Name
ans = Sensor Array Amplitudes
h2=h; % We will make a copy handle object h2.Name='New Name'; % Change name string property of new object h.Name % Original name property has been overwritten
ans = New Name
This is because if you copy a handle class their data properties are not copied.
This may remind you of how you work with handle graphics handles such as for a figure or an axes which have a similar behavior but they are not true objects and just integer numbers.
Method Return Arguments
Let's now look at the related issue of return method return arguments.
One of the capabilities of sensors arrays used in this way is that you can steer them in different directions electronically, not mechanically, by multiplying the received data with a complex phase shift. To do that it must modify the data property. In both classes, I have implemented a method which steers the array.
Value Class
If we look at the value class steer method, we see that if the method modifies the object, it needs to return it as an output argument.
dbtype +valueImp\sads.m 100:107
100 function obj=steer(obj,theta) 101 % STEER Steer array electronically by angle theta (in degrees), returning a new sensor array data set 102 % Example: 103 % s=steer(s,10); 104 delta=obj.Spacing; thetaR=theta*(pi/180); 105 Wc=2*pi*(obj.c/obj.Wavelength); % Source frequency in radians per sec 106 phaseShift=exp(-j*Wc*delta*(0:obj.NumSensors-1)*sin(thetaR)/obj.c); 107 obj.Data=bsxfun(@times,obj.Data,phaseShift); % Multiply by phaseshift
To show the steering working, I will check the current angles of the sources of the value object.
doa(v) % Check DOA angles
ans = -9.7080 19.4712
v=steer(v,10); % Steer the array by 10 degrees, returning the object doa(v) % Then we see the sources angles have moved by 10 degrees
ans =
0.2247 30.3899
Handle Class
With handle classes, methods that modify the object do not need to return it as an output argument. Here is the handle class steer method.
dbtype +handleImp\sads 98:106
98 function steer(obj,theta) 99 % STEER Steer array electronically by angle theta (in degrees), returning a new sensor array data set 100 % Example: 101 % s=steer(s,10); 102 103 delta=obj.Spacing; thetaR=theta*(pi/180); 104 Wc=2*pi*(obj.c/obj.Wavelength); % Source frequency in radians per sec 105 phaseShift=exp(-j*Wc*delta*(0:obj.NumSensors-1)*sin(thetaR)/obj.c); 106 obj.Data=bsxfun(@times,obj.Data,phaseShift); % Multiply by phaseshift
doa(h) % We check DOA angles for the handle class
ans = -9.7080 19.4712
steer(h,10); % Steer by 10 degrees, no need to return object doa(h) % See the sources angles have moved by 10 degrees
ans =
0.2247 30.3899
