How can I include a subclass definition file into an Octave class - class

I have two octave classes defined in the same directory:
/home/me/octave/#myclass/myclass.m
/home/me/octave/#mysubclass/mysubclass.m
mysubclass is a subclass of myclass:
mysubclass.m:
classdef mysubclass < handle
properties
my_property = 0;
endproperties
methods
function property = get()
property = my_property;
endfunction
endmethods
endclassdef
myclass.m:
classdef myclass < handle
properties
subclass = mysubclass();
endproperties
methods
function sub = get()
sub = subclass;
endfunction
endmethods
endclassdef
However I don't seem to be able to 'include' the subclass definition in the same way as I might for e.g. C++. I tried adding
addpath("../#mysubclass/");
at various points in myclass.m, but I get a syntax error.
Can someone help?

Related

How do I use static factory method in matlab package?

I have following class definition under +mypackage\MyClass.m
classdef MyClass
properties
num
end
methods (Static)
function obj = with_five()
obj = MyClass(5);
end
end
methods
function obj = MyClass(num)
obj.num = num;
end
end
end
I use with_five() as a static factory method.
Following script should create two objects.
import mypackage.MyClass
class_test1 = MyClass(5);
class_test2 = MyClass.with_five();
class_test1 has been created.
For class_test2 it says:
Error using MyClass.with_five
Method 'with_five' is not defined for class 'MyClass' or is removed from MATLAB's search path.
Error in Testpackage (line 4)
class_test2 = MyClass.with_five();
When I put MyClass.m outside of a package folder and remove the "import" statement, it works.
What am I doing wrong?
There are several wonky things in MATLAB with packages and with static methods.
First, functions within a package must use the package name to reference other functions or classes within the same package (see here). So the static method mypackage.MyClass.with_five() must be declared as follows:
methods (Static)
function obj = with_five()
obj = mypackage.MyClass(5);
end
end
Without this, I see:
>> mypackage.MyClass.with_five
Undefined function or variable 'MyClass'.
Error in mypackage.MyClass.with_five (line 8)
obj = MyClass(5);
Second, static class methods (at least the ones for classes inside packages) are not loaded until an object of the class is created. So we need to call the class constructor first:
>> clear classes
>> mypackage.MyClass.with_five
Undefined variable "mypackage" or class "mypackage.MyClass.with_five".
>> mypackage.MyClass(1);
>> mypackage.MyClass.with_five
ans =
MyClass with properties:
num: 5
The same is true if we import the class:
>> clear classes
>> import mypackage.MyClass
>> MyClass.with_five
Undefined variable "mypackage" or class "mypackage.MyClass.with_five".
>> MyClass(3);
>> MyClass.with_five
ans =
MyClass with properties:
num: 5
This second point was true in R2017a (where the outputs above were generated), but is no longer true in R2021a. I don't know in which release of MATLAB this was fixed, but in R2021a it is no longer necessary to create an object of a class to use its static method.
I think what you are missing is the fact that when you import a static method, you have to import the class name and the method name (https://au.mathworks.com/help/matlab/matlab_oop/importing-classes.html)
This works:
classdef MyClass
properties
num
end
methods (Static)
function obj = with_five()
obj = MyClass(5);
end
end
methods
function obj = MyClass(num)
obj.num = num;
end
end
end
Then do the following:
>> import MyClass.with_five
>> x = with_five
Output:
x =
MyClass with properties:
num: 5
That being said: don't create an object in a member function of its own class! As you suggest, a better choice is to move the factory to a different class. If you wanted to make a bunch of chainsaws, you would never go about trying to design a chainsaw that has a button on it that builds chainsaws. You would rather design a factory that can produce chainsaws that are designed to cut down trees.
A 'static factory' is not a bad thing. This is actually a pretty common pattern especially in C#. However, the factory is always its own class. Calling that method from another object that inherits from or extends that class (which I'm not sure you can even do in Matlab...) would most certainly be confusing if not deadly. I also can't think of any reason you would ever need to do this. In fact I don't understand why with_five() should be static at all

How to make property definition using own class in Matlab?

In Matlab I have the package "+mypackage". All the following definitions are under this folder/package.
MyClass.m
classdef MyClass
properties
prop1 MyProperty
end
methods (Static)
function obj = with_five()
obj = mypackage.MyClass(5);
end
end
methods
function obj = MyClass(num)
obj.prop1 = mypackage.MyProperty(num);
end
end
end
MyProperty.m
classdef MyProperty
properties
num double
end
methods
function obj = MyProperty(val)
obj.num = val;
end
end
end
So in MyClass.m I define the prop1 property to be an object of class MyProperty.
Now I would like to create objects with this script.
import mypackage.MyClass
class_test1 = MyClass(5);
class_test2 = MyClass.with_five();
When I run it I get following errors:
Error using Testpackage (line 3)
Error defining property 'prop1' of class 'mypackage.MyClass':
Class named 'MyProperty' is undefined or does not support property validation.
When I remove the property definition from MyClass.m it works.
Is there a way to define properties to be an object of an own class in Matlab?
Thank you Wolfie your Help!
I changed the definition for prop1 to mypackage.MyProperty.
My Class definition looks now like this:
classdef MyClass
properties
prop1 mypackage.MyProperty
end
methods (Static)
function obj = with_five()
obj = mypackage.MyClass(5);
end
end
methods
function obj = MyClass(num)
obj.prop1 = mypackage.MyProperty(num);
end
end
end
Its necessary to point to MyProperty inside my package mypackage.
Otherwise Matlab is not able to find it.
I found it in the Matlab help:
https://de.mathworks.com/help/matlab/matlab_oop/scoping-classes-with-packages.html?s_tid=srchtitle#brfynt_-3

Matlab: How to restict access to sub-class of abstract class method

Lets have a following three classes:
% Main class
classdef MjrClass < handle
properties (SetAccess = immutable, GetAccess = public)
cls;
end
methods (Access = public)
function self = MjrClass()
self.cls = SubClass(2);
end
end
end
% Abstract class
classdef (Abstract) AbsClass < handle
properties (SetAccess = immutable, GetAccess = protected)
p;
end
methods (Access = {?MjrClass})
function self = AbsClass(parent)
self.p = parent;
self.do();
end
end
methods (Access = public)
function show(self)
fprintf('self.p: %d\nself.c: %d\n', self.p, self.c)
end
end
end
% Sub-Class
classdef SubClass < AbsClass
properties (SetAccess = private, GetAccess = public)
c;
end
methods (Access = private)
function do(self)
self.c = self.p*2;
end
end
end
The logic is following. Main class MjrClass defines interface for end user. Inside, it creates (in general) several instances of SubClass class. Since those share some properties and methods they all inherit from AbsClass class. And because the AbsClass class alone has no purpose, it is defined as abstract class.
However as it is, Matlab complains it "Cannot access method 'AbsClass' in class 'AbsClass'". The problem is obviously the Access property of constructor method. But if I leave it public it does not reflect the fact that it shoould be instantiated only within MjrClass class.
The same problem applies to do() method of SubClass class, where Access = private should restrict the method to be called only once within the AbsClass constructor, not allowing user to call it.
The access specifier for the AbsClass constructor doesn't actually allow AbsClass to call that method. So, the fix is simple, allow AbsClass (and its subclasses) to call its own constructor, like this:
methods (Access = {?MjrClass, ?AbsClass})
function obj = AbsClass(...)
....

Variable YYY originally saved as a XXX cannot be instantiated as an object and will be read in as a uint32

I've made a mistake and recorded a bunch of important data using a class definition that I can't find anymore. The methods are not important, I just want the data; a struct conversion would be fine.
Is there any way I can recover this?
Googling it did not help.
The solution is to create a new class that overloads the loadobj method. See here for more information regarding the load process for classes.
I replicated your problem by creating a class:
classdef myclass
properties
Prop1
Prop2
Prop3
end
methods
function obj = myclass(a,b,c)
obj.Prop1 = a;
obj.Prop2 = b;
obj.Prop3 = c;
end
end
end
Then I created an object of this class and saving it to a file "x.mat":
x = myclass('a',56,[1,2,3]);
save x
Next, I deleted the myclass file and did clear classes. This put me in your situation.
I then created a new myclass class that overloads the loadobj method:
classdef myclass
properties
data
end
methods (Static)
function obj = loadobj(s)
obj = myclass;
obj.data = s;
end
end
end
Note how it doesn't know any of the original properties. This does not matter. If any of the original properties is missing when loading an object from a MAT-file, loadobj will be called with s being a struct containing all the properties of the original object.
With this new class definition, load x created an object x of class myclass, where x.data was a struct containing the properties of the object saved in "x.mat".

Protected property is not accessible if defined as abstract

Using Matlab R2012a, I have the following class hierarchy:
classdef Parent < handle
properties (Abstract, SetAccess = protected)
Limit
end
end
classdef SimpleChild < Parent
properties (SetAccess = protected)
Limit = 1.0
end
end
classdef ExtendedChild < Parent
properties (Access = private)
Child = SimpleChild
end
properties (Dependent, SetAccess = protected)
Limit
end
methods
function this = ExtendedChild
this.Limit = 2;
end
function output = get.Limit(this)
output = this.Child.Limit;
end
function set.Limit(this,input)
this.Child.Limit = input;
end
end
end
This a simple example where the "Parent" class defines an abstract "Limit" property, which is implemented in both the "SimpleChild" and the "ExtendedChild" class. The "ExtendedChild" class encapsulates a private instance on the "SimpleChild" class and forward the access methods (get/set) to the private instance. Constructing an "ExtendedChild" instance fails with the following message:
>> obj = ExtendedChild
Setting the 'Limit' property of the 'SimpleChild' class is not allowed.
Error in ExtendedChild/set.Limit (line 16)
this.Child.Limit = input;
Error in ExtendedChild (line 10)
this.Limit = 2;
I would have expected the "Limit" property to be settable since it is defined in the "Parent" class with a protected SetAccess. I can make the problem disappear if the property is implemented directly in the "Parent" class, but then I cannot redefine it as dependent in the "ExtendedChild" class, which is the point of the construction (separation of interface and implementation).
Can someone tell me if I'm doing something wrong?
Since the Limit property of SimpleChild is protected, you can only set its value from SimpleChild or a subclass of SimpleChild, which is not the case for ExtendedChild.
I'm not entirely sure what you're trying to achieve, so can't really advise on what the "best" way to do it might be. But I would guess that whatever you want, it's unlikely that having a set method for a Dependent property is the right way to achieve it - there are only very rare reasons why you might want to do that.