Initialize child before parent - do not call parent contructor - matlab

In MatLab, i have a superclass A that takes some parameters, x and y
classdef A < handle
properties
x;
y;
z;
end
methods
function this = A(x, y)
this.x = x;
this.y = y;
this.initialize();
end
function initialize(this)
this.z = this.x + this.y;
end
end
end
The initialize method is supposed to do some initial calculations to fasten computation later.
Now i want to create a child class B of A, with it's own inialization, but B should be initialized before A.
classdef B < A
properties
p
end
methods
% B takes another parameter p
function this = B(p)
% Since B is a subclass of A, and A takes some parameters we have to
% call the constructer of A as the first thing.
this = this#A([], []);
this.p = p;
end
function initialize(this)
this.x = this.p(1);
this.y = this.p(2);
% This is when initialize of A should be called.
end
end
end
Basically i just want to initialize B before A, but because the constructer of the parent have to be called as the first thing, i cannot figure out how to do this.
In PHP I would do something like this
class A {
public function __construct($x, $y) {
$this->x = $x;
$this->y = $y;
$this->initialize();
}
public function initialize() {
$this->z = $this->x + $this->y;
}
}
class B extends A {
public function __construct($p) {
// Does not call the parent constructor.
$this->p = $p;
$this->initialize();
}
public function initialize() {
$this->x = $this->p[0];
$this->y = $this->p[1];
parent::initialize(); // Now we are ready to initialize A
}
}
Is there a smart way to design what i want in MatLab? Do i have to give up the inheritance of A in class B?

The complication arises since:
If you create a subclass object, MATLABĀ® calls the superclass constructor to initialize the superclass part of the subclass object. By default, MATLAB calls the superclass constructor without arguments. [src]
You can get around explicitly calling the superclass constructor by wrapping its work in an if-statement dependent on how many arguments it was passed (nargin):
function this = A(x, y)
if (nargin ~= 0) % or (nargin == 2) in this case
this.x = x;
this.y = y;
this.initialize();
end
end
And then B's methods would look like:
function this = B(p)
this.p = p;
this.initialize();
end
function initialize(this)
this.x = this.p(1);
this.y = this.p(2);
initialize#A(this);
end
It may just be error in the post, but A's initialize method is referencing undefined variables x and y and not their properties. It should be:
function initialize(this)
this.z = this.x + this.y;
end

This goes against the principles of OOP. What you are trying to achieve basically rules out that B should be derived from A. From what I can tell, you really want to overload the constructor of A. Either do this using a nargin check in A, or if you really want to have a B for whatever reason, just use: this = this#A(p(1), p(2); in the constructor of B instead, to properly call the constructor of A (and get rid of the property p).
This is how you would simulate to overload the constructor by using nargin:
classdef A < handle
properties
x;
y;
z;
end
methods
function this = A(x, y)
if nargin==1 % 'p' was passed as 'x'
this.x = x(1);
this.y = x(2);
else
this.x = x;
this.y = y;
end
this.initialize();
end
function initialize(this)
this.z = this.x + this.y;
end
end
end
This is how you would derive B from A, with a proper call of A's constructor:
classdef B < A
methods
function this = B(p)
this = this#A(p(1), p(2));
end
end
end

Related

In matlab, I got different values in a method of class and out

In the matlab, I defined a class and instantiated the class in another script, but I got different values in and out of the method. My matlab code are shown bellow:
test_add.m
classdef test_add
properties
a
b
end
methods
function obj = test_add(a, b)
obj.a = a;
obj.b = b;
end
function c = add_1(obj)
c = obj.a + 1;
end
function inter(obj, t)
for i = 1:t
obj.a = obj.add_1();
end
fprintf('In the method:\n');
fprintf('a = %d\n',obj.a);
fprintf('b = %d\n',obj.b);
disp('=======================');
end
end
end
main.m
tt = test_add(1,2);
tt.inter(3);
fprintf('Out of the method:\n');
fprintf('a = %d\n',tt.a);
fprintf('b = %d\n',tt.b);
output:
In the method:
a = 4
b = 2
=======================
Out of the method:
a = 1
b = 2
In Matlab there are two type of classes: handle class and Value class. If you said nothing you get the Value class. Most of the OO languages out there are using handle class semantic.
So, you have two options:
Change you class to handle class by inheriting from handle
classdef test_add < handle
Stay with Value class and change your inter function to return obj.
But then, in main call obj=tt.inter(3) to get the updated object.
function obj = inter(obj, t)
for i = 1:t
obj.a = obj.add_1();
end
fprintf('In the method:\n');
fprintf('a = %d\n',obj.a);
fprintf('b = %d\n',obj.b);
disp('=======================');
end
It's a problem of value class vs handle class, the solution is:
test_add.m
classdef test_add < handle
...
end
Then, the output is:
In the method:
a = 4
b = 2
=======================
Out of the method:
a = 4
b = 2

matlab how to call a class method that changes prop from another class method

If I call a method (receiving and returning obj) it changes my property.
But if I call that method from another method it fails. I tried all kinds of ways but still failing.
classdef AClass
properties
A;
end
methods
function obj = ChangeA(obj, v)
obj.A = v;
end
function obj = CallChangeA(obj)
obj.ChangeA(4);
%obj = obj.ChangeA(4);
%ChangeA(obj, 4);
%obj = ChangeA(obj, 4);
% none of these works
end
end
end
% ------ script:
a1 = AClass;
a1.A = 1;
a1.ChangeA(2); % a1.A = 2
a2 = AClass;
a2.A = 3;
a2.CallChangeA(); % a2.A = 3 !!! not four
How do I write the code so calling from 1 method to the other updates the property?
Other than the obvious typos in your example code, as I commented above, I would highly suggest taking a look at the difference between MATLAB's Handle and Value classes. By default, MATLAB classes are value classes, so each time the object is passed to a function an independent copy is created. If you're making changes to this object then you need to return it as an output:
classdef AClass
properties
A;
end
methods
function obj = ChangeA(obj, a)
obj.A = a;
end
function obj = CallChangeA(obj)
obj = obj.ChangeA(4);
end
end
end
Which functions as expected:
>> a1 = AClass;
>> a1.A = 1
a1 =
AClass with properties:
A: 1
>> a1 = a1.CallChangeA()
a1 =
AClass with properties:
A: 4
Handle classes, on the other hand, are references to a single underlying object, allowing for (among other things) in place modification of the object:
classdef AClass < handle
properties
A;
end
methods
function ChangeA(obj, a)
obj.A = a;
end
function CallChangeA(obj)
obj.ChangeA(4);
end
end
end
Which also functions as expected:
>> a1 = AClass;
>> a1.A = 1;
>> a1.A
ans =
1
>> a1.CallChangeA()
>> a1.A
ans =
4

Use one set method for multiple properties MATLAB

I have several properties that use essentially the same set method:
classdef MyClass
properties
A
B
end
methods
function mc = MyClass(a,b) % Constructor
mc.A = a;
mc.B = b;
end
function mc = set.A(mc, a) % setter for A
if a > 5
mc.A = a;
else
error('A should be larger than 5');
end
end
function mc = set.B(mc, b) %setter for B
if b > 5
mc.B = b;
else
error('B should be larger than 5');
end
end
end
end
Is there a way to use only one set function for variables A and B? (Please note that the error function use the property names as strings.)
Is it suggested to use only one set function? What are the possible drawbacks of using one set function?
The only real way is to extract the common code to another function, and call it from the setters:
classdef MyClass
properties
A
B
end%public properties
methods
function mc = MyClass(a,b) % Constructor
mc.A = a;
mc.B = b;
end
function mc = set.A(mc, value) % setter for A
mc = mc.commonSetter(value, 'A');
end
function mc = set.B(mc, value) %setter for B
mc = mc.commonSetter(value, 'B');
end
end%public methods
methods(protected = true)
function mc = commonSetter(mc, property, value)
if value <= 5;
error([property ' should be less than 5');
end
mc.(property) = value;
end%commonSetter()
end%protected methods
end%classdef

changing class properties with its methods

I'd like to change my class properties with a method defined for that class:
classdef triangle<handle
properties
a
h
end
methods
function obj = triangle()
obj;
end
function obj = setProps(obj, a, h)
obj.a = a;
obj.a = h;
end
end
end
Calling:
t = triangle();
t.setProps(a, h);
It's not working at all - I get this error:
The class 'handle' is not a super-class of class 'triangle', as required to invoke a super-class constructor or method.
Error in triangle (line 13)
function obj = triangle()
I'm using matlab 2012a. My code is based on this example: link
Try clear before doing this. It is possible that you've overwritten handle with something. Otherwise, this works for me on Matlab 2012a:
clear;
a = 'hello';
h = 1;
t = triangle();
t.setProps(a, h);

Use a property of a classdef in another .m file?

Here is my code:
f.m:
classdef f < handle
properties (Access = public)
functionString = '';
x;
end
methods
function obj = f
if nargin == 0
syms s;
obj.x = input('Enter your function: ');
obj.functionString = ilaplace(obj.x);
end
end
function value = subsref(obj, a)
t = a.subs{:};
value = eval(obj.functionString);
end
function display(obj)
end
end
end
test.m:
syms s t;
[n d] = numden(f.x); % Here I want to use x, which is the user input, How can I do such thing?
zeros = solve(n);
poles = solve(d);
disp('The Poles:');
disp(poles);
disp('The Zeros:');
disp(zeros);
disp('The Result:');
disp(z(t));
disp('The Initial Value:');
disp(z(0));
disp('The Final Value:');
disp(z(Inf));
When I type test in the command window, it tells me the following:
>> test
??? The property 'x' in class 'f' must be accessed from a class instance because it
is not a Constant property.
As Alex points out, you need an instance of f to access the member property x, like so:
myf = f();
f.x
You do not need an accessor method to get at x as it is defined as a public property. If you chose to make x private, then you'd need an accessor method something like this:
function x = getX( obj )
x = obj.x;
end