Using Multiple Classes/Files MATLAB

Hello,
I am having some trouble understanding object oriented progrraming in MATLAB.
I have created a script .m file which I want my general code to run in and produce the output(s) that I want.
I have also create three separate .m files, each of which contain three different classes, and these classes each have a constructor as well as a function which returns a public variable of the class which is initialized thru the constructor.
My goal is to create an instance of these three different classes in the script .m file as I earlier mentioned, as I want to access this public variable from each class in the main script file as it is needed to run my program/produce the output.
For reference, here is an example of the class I am talking about:
classdef className
properties
%general variables
%variable i want accessed the main script
end
methods
function r = className(%general variables)
%variable i want accessed=(math operation using general
%variables)
r=className
end
function randomName = randomName()
randomName=%variable i want accessed int he main script
end
end
end

 Accepted Answer

Create Class Files: You mentioned that you have three separate .m files, each containing a class. Let's assume these class files are named Class1.m, Class2.m, and Class3.m. Inside each of these files, define your classes similar to what you've shown in your example.
Class Definitions: Your class definitions in Class1.m, Class2.m, and Class3.m should look something like this:
classdef Class1
properties
% Define properties
Prop1
end
methods
function obj = Class1(arg1, arg2)
% Constructor
% Perform calculations using arg1 and arg2
obj.Prop1 = % calculated value;
end
function result = SomeMethod(obj)
% Method
result = % some calculation using obj.Prop1;
end
end
end
Repeat this structure for Class2.m and Class3.m, adjusting property names, constructor calculations, and methods as needed.
Main Script File: Now, in your main script file (let's call it mainScript.m), you can create instances of these classes and call their methods. Here's an example:
% Create instances of the classes using the constructors
obj1 = Class1(arg1_value, arg2_value);
obj2 = Class2();
obj3 = Class3();
% Call methods and access properties
result1 = obj1.SomeMethod();
result2 = obj2.SomeMethod();
result3 = obj3.SomeMethod();
% Access properties
prop1_value = obj1.Prop1;
Replace arg1_value and arg2_value with the actual values you want to pass to the constructors of Class1.
In your example, it seems like the classes are missing some details, but the general structure should be similar to what I've outlined. Here's a breakdown of what's happening:
You define classes in separate .m files.
Each class has properties (variables) and methods (functions).
The constructor (function obj = Class1(arg1, arg2)) initializes the properties based on the arguments you provide when creating an instance.
Methods can access the properties and perform calculations using them.
In the main script, you create instances of the classes and use their methods and properties.

8 Comments

Thomas Bewley
Thomas Bewley on 29 Apr 2024
Moved: Stephen23 on 29 Apr 2024
Follow-up question, if you don't mind: if I write two class files to define two classes, say my_uint32 and my_uint64, each with constructors and methods (functions) designed to act on instances of these classes (for example, a32 and a64, respectively). Matlab will look in the class file my_uint32.m to find functions that operate on a32, and will look in my_uint64.m to find functions that operate on a64. Fair enough. My question: where will Matlab look to find functions that act on both a32 and a64? I need to define some of those, and need to know where to put them...
Define them as plain functions (not methods.) For example, the lcm function in MATLAB:
which -all lcm
/MATLAB/toolbox/matlab/specfun/lcm.m /MATLAB/toolbox/symbolic/symbolic/@sym/lcm.m % sym method
is defined as a method for sym objects but is also defined as a regular function. So you can pass a double array into lcm:
lcm(5, 7)
ans = 35
or an int32 array:
lcm(int32(5), int32(7))
ans = int32 35
or an instance of any class that defines the functions/methods that lcm uses (round, ne, lt, times, ldivide, and gcd. And parenthesis indexing.)
dbtype lcm.m
1 function c = lcm(a,b) 2 %LCM Least common multiple. 3 % LCM(A,B) is the least common multiple of corresponding elements of 4 % A and B. The arrays A and B must contain positive integers 5 % and must be the same size (or either can be scalar). 6 % 7 % Class support for inputs A,B: 8 % float: double, single 9 % integer: uint8, int8, uint16, int16, uint32, int32, uint64, int64 10 % 11 % See also GCD. 12 13 % Copyright 1984-2012 The MathWorks, Inc. 14 15 if any(round(a(:)) ~= a(:) | round(b(:)) ~= b(:) | a(:) < 1 | b(:) < 1) 16 error(message('MATLAB:lcm:InputNotPosInt')); 17 end 18 c = a.*(b./gcd(a,b));
Thank you for your quick reply!
That didn't quite address my question though. In each class definition, I'm specifically trying to define, e.g., the special method called plus(A,B), to overload the + operator, when A and B are instances of different (but compatible) user-defined classes (like, a32 and a16 mentioned previously, defined as instances of the my_uint32 and my_uint16 classes - I also have similar my_uint8 and my_uint64 classes...). So I need to know which class definition file Matlab looks to first when trying to find the function that tells it how to calculate the sum of, e.g., a32+a16. Is it consistently the class corresponding to the first argument? Unless that argument is a Matlab intrinsic class, then it looks at the class corresponding to the second argument? Or something else? Or maybe is this choice not actually uniquely defined by the Matlab standard?
Thomas Bewley
Thomas Bewley on 29 Apr 2024
Edited: Thomas Bewley on 29 Apr 2024
The behavior that I'm seeing, when the two areguments to the + (plus) method are two user-defined classes, is that it picks up which class definition file to look in based the user-defined class of the first argument. See example below. I guess my question is, is this behavior expected to be consistent? If so I should be able to make the nitty-gritty type conversions happening behind the scenes such that everything just works...
>> a8=RR_uint8(5)
a8 =
RR_uint8 with value 0x05 = 5
>> b16=RR_uint16(7)
b16 =
RR_uint16 with value 0x0007 = 7
>> a8*b16
in RR_uint8
ans =
RR_uint8 with value 0x23 = 35
>> b16*a8
in RR_uint16
ans =
RR_uint16 with value 0x0023 = 35
Ah. In that case read through this documentation page, especially the second section.
If both your my_uint32 class and your my_uint16 class define the plus method and neither declares the other as an inferior class, the left-most input wins. As an example, both datetime and duration define a plus method.
dt = datetime('now');
du = duration(1, 2, 3);
If we were to call plus on one of those objects and a double array, we call the method.
which plus(dt, 1)
/MATLAB/toolbox/matlab/datatypes/datetime/@datetime/plus.m % datetime method
which plus(du, 1)
/MATLAB/toolbox/matlab/datatypes/duration/@duration/plus.m % duration method
But which one gets called when we add dt and du? And does the order matter?
which plus(dt, du)
/MATLAB/toolbox/matlab/datatypes/datetime/@datetime/plus.m % datetime method
which plus(du, dt)
/MATLAB/toolbox/matlab/datatypes/datetime/@datetime/plus.m % datetime method
The datetime method gets called, regardless of the order. That's because datetime lists duration as an inferior class.
metainformation = metaclass(dt);
{metainformation.InferiorClasses.Name}.'
ans = 3x1 cell array
{'duration' } {'calendarDuration' } {'matlab.graphics.axis.Axes'}
But if we had a table array, which doesn't list datetime as an inferior class (and neither does datetime list table as inferior), the left-most input "wins".
T = array2table(magic(4));
which plus(dt, T)
/MATLAB/toolbox/matlab/datatypes/datetime/@datetime/plus.m % datetime method
which plus(T, dt)
/MATLAB/toolbox/matlab/datatypes/tabular/@tabular/plus.m % table method
+1, excellent answer. I clearly need uint8 to be "inferior" to uint16, etc, so then I can convert the smaller class to the bigger class before doing the add, regardless of the order. Thank you sir.
I assume you mean my_uint8 and my_uint16, not the types included in MATLAB. You cannot change how uint8 and uint16 are defined or have them list inferior classes.
of course. And it is done. :) FYI, I implemented a possibly interesting behavior, that automatically extends the data type to the next class up when it is necessary to prevent overflow, as illustrated in the snippet below. Perhaps the most useful part is that it throws an error, instead of returning a wrong result, when overthrow happens (unlike Matlab builtin). My class definitions that result in this behavior are available for free (under BSD 3-clause) at the link below (feel free to clone the entire RR repo, I'm collecting some hopefully useful stuff there). :)
>> A=RR_int8(1); for i=2:21, A=A*i, end
A =
RR_int8 with value 0x02 = 2
A =
RR_int8 with value 0x06 = 6
A =
RR_int8 with value 0x18 = 24
A =
RR_int8 with value 0x78 = 120
Warning: product overflow in RR_int8, increasing int type to RR_int16.
A =
RR_int16 with value 0x02D0 = 720
A =
RR_int16 with value 0x13B0 = 5040
Warning: product overflow in RR_int16, increasing int type to RR_int32.
A =
RR_int32 with value 0x00009D80 = 40320
A =
RR_int32 with value 0x00058980 = 362880
A =
RR_int32 with value 0x00375F00 = 3628800
A =
RR_int32 with value 0x02611500 = 39916800
A =
RR_int32 with value 0x1C8CFC00 = 479001600
Warning: product overflow in RR_int32, increasing int type to RR_int64.
A =
RR_int64 with value 0x000000017328CC00 = 6227020800
A =
RR_int64 with value 0x000000144C3B2800 = 87178291200
A =
RR_int64 with value 0x0000013077775800 = 1307674368000
A =
RR_int64 with value 0x0000130777758000 = 20922789888000
A =
RR_int64 with value 0x0001437EEECD8000 = 355687428096000
A =
RR_int64 with value 0x0016BEECCA730000 = 6402373705728000
A =
RR_int64 with value 0x01B02B9306890000 = 121645100408832000
A =
RR_int64 with value 0x21C3677C82B40000 = 2432902008176640000
Error using *
product overflow in RR_int64.
>>
I got started on all this because I needed standard integer division [Q,R]=A/B defined, where (as opposed to / in Matlab),
A = (A/B)*B + R, where sign(R)=sign(A) and |R|<|B|, where A=dividend, B=divisor, thus satisfying the following standard identities: (−A)/B = −(A/B) = A/(−B).
This is now implemented in my family of int, classes which includes:
RR_int8, RR_int16, RR_int32, RR_int64, and
RR_uint8, RR_uint16, RR_uint32, RR_uint64, RR_uint128, RR_uint256, RR_uint512, RR_uint1024
Using this (and my random number generation routines) the following calculations (at all levels of precision implemented) give C=0, |R|<|B|, sign(R)=sign(A), and Q1=Q2=Q3 in the following types of tests:
>> A=RR_rand_RR_int([-10^16,10^16]), B=RR_rand_RR_int([-10^10,10^10])
if B~=0, [Q,R]=A/B, C=(Q*B+R)-A, Q1=(-A)/B, Q2=-(A/B), Q3=A/(-B), end
A =
RR_int64 with value 0xFFFF49BC1F043B62 = -200402653660318
B =
RR_int64 with value 0x000000024CF63C68 = 9881140328
Q =
RR_int64 with value 0xFFFFFFFFFFFFB0C7 = -20281
R =
RR_int64 with value 0xFFFFFFFF3E7BC68A = -3246668150
C =
RR_int64 with value 0x0000000000000000 = 0
Q1 =
RR_int64 with value 0x0000000000004F39 = 20281
Q2 =
RR_int64 with value 0x0000000000004F39 = 20281
Q3 =
RR_int64 with value 0x0000000000004F39 = 20281
>>

Sign in to comment.

More Answers (0)

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!