I need to know if there is a way in matlab to define interface superclass for both handle and non-handle subclasses? If in hierarchy there is a handle class, all classes must be handle too and in matlab the interface is defined as abstract class. So it can't be done this way.
class A < handle
....
end
class AA < A
....
methods
function foo
end
end
end
class B
....
methods
function foo
end
end
I want to create some kind of container with classes AA (handle) and B (non-handle) to ensure they both have function foo. Is there way to do this?
You should be able to do:
classdef (Abstract, HandleCompatible) A
methods (Abstract)
function foo
end
end
classdef AA < A & handle
methods
function foo
...
end
end
end
classdef B < A
methods
function foo
...
end
end
end
Here you are marking A as Abstract, with an abstract method foo. So AA and B must both implement foo. You also mark A as HandleCompatible, which means that subclasses can be handles.
Then AA inherits from both A and handle, but B inherits only from A and is a value class. Both implement foo.
Note that you may need to take care in the way that you implement foo in each class, as the necessary function signature can vary between handle and value classes.
Related
In Matlab (2017b) I'm trying to implement a superclass with a yet undefined abstract property.
classdef Class_Test1
properties (Abstract=true)
obj
end
end
Subclasses should then implement this property and restrict it to a certain class, e.g.:
classdef Class_Test2 < Class_Test1
properties
obj#double = 123;
end
end
a = Class_Test2; now throws an error:
The property 'obj' restriction defined in class 'Class_Test2' must match
the property definition in base class 'Class_Test1'.
Is there no way to specify the class / type of obj in the implementation of the abstract class or am I missing something?
In the end I would like obj to be abstract in Class_Test1 to implement several subclasses, which will hold objects of different classes in obj.
Any help appreciated ...
MATLAB classes are weird... or in any case very different from what you expect from a class if you've learnt about classes in any other programming language.
One aspect of MATLAB is that it's an interpreted language. Stuff is evaluated when executed, not when compiled. So code doesn't always need to make sense.
So, we can solve your issue like this:
classdef (Abstract) foo
methods
function c = getclass(in)
c = class(in.obj);
end
end
end
The function foo.getclass seems to not make sense, since foo doesn't have a property obj. But because foo is abstract, we're never going to have an object of class foo on which we'll call the getclass method. Whenever getclass is called, it'll be a derived class. So, if we want to use this getclass method, we need to make sure that the derived class has a property obj:
classdef foo_uint8 < foo
properties
obj#uint8 = uint8(1);
end
end
It is now possible to call foo_uint8.getclass:
>> a = foo_uint8;
>> a.getclass
ans =
'uint8'
OK, so after looking into this further it seems that this is a deliberate limitation based on the design of Matlab. I'm not too familiar with OOP in other languages but would be interested to learn if this is an general OOP fundamental or rather Matlab specific.
As a workaround I have come up with the following solution:
classdef (Abstract) Class_Test1 < handle
properties
Obj
end
properties (Abstract = true, Constant)
ObjClass#char
end
methods
function set.Obj(obj_in,in)
if isa(in, obj.ObjClass)
obj_in.Obj = in;
end
end
end
end
... and the implementation ...
classdef Class_Test2 < Class_Test1
properties (Constant)
ObjClass#char = 'double'; % Define the allowed class here ...
end
end
I would still be interested to learn about other possible solutions.
I have a superclass
classdef superclass
properties
a
b
methods
% constructor
function obj = superclass(a,b)
obj.a = a;
obj.b = b;
end
... some code...
function c = plus(obj1,obj2)
c = superclass(obj1.a+obj2.b,obj1.b)
end
(There is a lot of type checking and error throwing but this is the gist of it). This class has almost all of the operators are overloaded like this. Those which are not, throw an error. Now I have derived another class from this which adds some properties.
classdef subclass < superclass
properties
p
q
methods
... constructor and such...
end
Now when I do any operation on this class like adding it will return an object of the superclass (because of my overloaded plus function). The only way I see to fix this is overload all of those functions once again. That is tedious, is there a better way?
I generally find the set/get interface defined in hgsetget very useful for setting and getting multiple parameters at the same time. I recently found it was especially suited for object construction.
Example:
classdef testclass < hgsetget
properties
A
B
C
D
end
methods
function obj = testclass(varargin)
if ~isempty(varargin)
set(obj,varargin{:})
end
end
end
end
Usage:
>> a = testclass('A',1,'B',2)
a =
testclass handle
Properties:
A: 1
B: 2
C: []
D: []
Despite the slowness of this interface I'm really happy of the flexibility it provides.
What is more annoying for my application is that I obtain a handle class (by inheritance from hgsetget).
To circumvent this my first guess was to construct an abstract class with my set/get definition inside. Very simply written it gives:
classdef (Abstract) myAbstractClass
methods
function obj = set(obj,varargin)
for i = 1:2:length(varargin)
obj.(varargin{i}) = varargin{i+1};
end
end
function val = get(obj,varargin)
val = cell(length(varargin),1);
for i = 1:length(varargin)
val{i} = obj.(varargin{i});
end
end
end
end
and then set it as superclass for my test class
classdef testclass < myAbstractClass
properties
A
B
C
D
end
methods
function obj = testclass(varargin)
if ~isempty(varargin)
set(obj,varargin{:})
end
end
end
end
However I must misunderstand something in the construction mechanism because here is what happens:
>> a = testclass('A',1,'B',2)
ans =
testclass
Properties:
A: 1
B: 2
C: []
D: []
Methods, Superclasses
a =
testclass
Properties:
A: []
B: []
C: []
D: []
Methods, Superclasses
If somebody knows the reason of this behavior, I'm totally open to her/his explanations
Thank you in advance
JM
Overall your design looks good, but within your constructor method testclass, you need to write
obj = set(obj,varargin{:});
Because you are using a value class rather than a handle class, you need to retrieve the output of your set method, otherwise you'll have set the property of something, and then discarded it and returned a completely different (and empty) obj as output.
Also, you need to add a semi-colon after the call to set; otherwise it will display the intermediate something.
You may also want to revise your opinion of handle classes; they're really very natural to use (just my opinion, but more natural in an OO context than value-behaviour).
I'm working on classes and their multiple inheritance, I have a problem which I couldn't solve after so many help, I have a class A which is base class and class B, which is its derive class. What I want is, the Constructor of class A with input arguments is to be calling in derived class B,supposed to be called in class B with its input arguments But unfortunately i have error Not enough input arguments. as Class B is expecting arguments but I want to give arguments as input in Class B like above.
What solution is to be suggested or appropriate in my case?
My Code: (Base Class A)
classdef A %base class
properties
arg1
end
properties
out
end
methods
function obj = A(arg1)
obj.arg1=arg1;
obj.out=[1 2 3;];
end
end
end
Derived Class B:
classdef B < A %derived Class
properties (Access=protected)
arg2
obj1
end
methods
function obj1 = B(arg2)
obj1.arg2=arg2;
A(obj1);
end
end
end
Call the constructor of superclass A like this:
B.m:
classdef B < A %derived Class
properties (Access=protected)
arg2
end
methods
function obj = B(arg1,arg2)
obj = obj#A(arg1);
obj.arg2 = arg2;
end
end
end
From the documentation:
By default, MATLAB calls the superclass constructor without arguments. If you want the superclass constructor called with specific arguments, explicitly call the superclass constructor from the subclass constructor. The call to the superclass constructor must come before any other references to the object.
Don't forget to clear all instances of both classes before trying new code, and clear A.m B.m just for good measure.
Usage:
>> myA = A(1)
myA =
A with properties:
arg1: 1
out: [1 2 3]
>> myB = B(1,2)
myB =
B with properties:
arg1: 1
out: [1 2 3]
I am trying to describe that an abstract class AA has an abstract property X of type BB. This property BB differs for different concrete subclasses of AA. This BB is also an abstract class, and its concrete subclasses will be used as X for different concrete subclasses of AA. However, when I tried to do that as the following code, I got an error message.
So first, AA and AA concrete are
classdef (Abstract) AA
properties (Abstract)
X#BB;
end
end
classdef AAconcrete < AA
properties
X#BBconcrete;
end
end
and BB and BBconcrete are
classdef (Abstract) BB < matlab.mixin.Heterogeneous
end
classdef BBconcrete < BB
end
When I tried to initiate AAconcrete, I got the following error message.
>> a = AAconcrete
Error using AAconcrete
The property 'X' restriction defined in class 'AAconcrete' must match the
property definition in base class 'AA'.
I understand that the error message said type BBconcrete is not the same as BB, although isa(BBconcrete,'BB') returns true. Even though if I don't declare X as type BB in the abstract class AA, the same error message appears.
I wonder what's the right way to describe such relationship, and your help is greatly appreciated!
Don't attempt to make MATLAB a strong typed programming language, that typically does not succeed. Use your base class and (if required) check the data types when writing:
classdef AAconcrete < AA
properties
X#BB;
end
methods
function set.X(obj,x)
assert(isa(x,'BBconcrete'));
obj.X=x;
end
end
end
In addition to Daniel's answer, I would suggest that attempting to redefine the type in AAConcrete for X is your problem. either remove the type definition in AA, or (my suggestion) remove it in AAConcrete, and use a set.X function to restrict the type in AA Concrete:
function set.X(obj, value);
validateattributes(value, 'BBConcrete', {'nonempty'});
obj.X = value;
end;