Recovering the built-in empty functionality when empty() is overloaded
3 ビュー (過去 30 日間)
古いコメントを表示
I am trying to create a custom class, say CustomClass, that will redefine parentheses indexing. One of the requirements of parentheses overloading is to overload the empty() method. I would ideally like the new method to continue returning a native empty object of the custom class, exactly as before empty() was overloaded.
I have not been able to find a way to do that. The command builtin('empty',CustomClass) isn't defined. The command empty(CommandClass) simply causes recursion... Nor does something like obj=empty@handle work.
Since there is conceptuably a distinct difference between a fully instantiated copy of the new custom class (even if this reports it's size as zero and itself as empty by overloading those methods too) and a true empty (non-instantiated) copy of the class I am wondering if there is any way to achieve what I need.
For example, a true empty copy of a class returns zero arguments when you access its properties. An instantiated copy returns the property values.
The sample code is:
classdef CustomClassA < handle
properties
prop1
end
methods (Static)
function obj=empty(varargin)
obj=CustomClassA;
end
end
end
classdef CustomClassB < handle
properties
prop1
end
% empty not overloaded
end
Getting the empty instances of both classes results in an instantiated object of CustomClassA and an empty object of CustomClassB
a=CustomClassA.empty
a =
CustomClassA with properties:
prop1: []
b=CustomClassB.empty
b =
0×0 CustomClassB array with properties:
prop1
class(a.prop1)
ans =
'double'
class(b.prop1)
Error using class
Not enough input arguments.
So my question basically is:
What can go in the CustomClassA empty() overload to recover the behaviour of CustomClassB.empty?
0 件のコメント
回答 (2 件)
Kyle
2023 年 11 月 3 日
Unfortunately, this can't be done using RedefinesParen with default property indexing. When you use the RedefinesParen mixin, you are a scalar object pretending to be an array. In a lot of places, you can pretend very convincingly! But when you pretend to be different sizes, you also pretend to be empty, since "emptiness" is based on your size. So whenever you pass an "array" of your object around, you are still technically passing a scalar object. As such, your properties are referenced as if you are a scalar as well.
However, this is different to the behavior when you index into your object with parenthesis. When you overload paren indexing with RedefinesParen, you can also return a variable number of outputs for paren reference. This depends on how you implement your parenListLength method. So it is possible that you could theoretically design your class so that class(b().prop) matches the behavior of class(a().prop). But you will still not be able to do so for b.prop directly, without referencing with parenthesis first.
0 件のコメント
chrisw23
2023 年 10 月 25 日
編集済み: chrisw23
2023 年 10 月 25 日
you have the option to define a constructor with arguments to define the state of the returned object
i.e.
classdef CustomClassA < handle
...
function CustomClassA(<arg>) % constructor
...
function delete(obj) % destructor
4 件のコメント
Kyle
2023 年 11 月 2 日
Hi Nicolas,
Walter is correct. Instantiation has specific mechanics that are not based on when a constructor is called.
To help illustrate things, I am going to try to clarify how empty and RedefinesParen work.
- empty: In my mental model, there way to think about an empty object is that at least one of its array dimensions is equal to zero. Recall that every variable in MATLAB is an array with dimensions. So, a 0x0 array would be empty, but so is a 2x2x5x0 array. This is true for all objects you define, including those with RedefinesParen. This is also why empty supports a size input. If you want to be thorough, you can tell your empty function to return different empty instances of your class based on what dimensions are passed into the empty method.
- RedefinesParen: When you use this, I find it helpful to remember that your class is a scalar (1x1) object pretending to be an array of objects. You are in control of the behavior of paren indexing into members of your class. This includes determining the dimensions of your object as well. And since you control the size that gets returned, you control when you pretend to be empty. If your class fits the scalar model, one option is to just inherit from Scalar instead and prohibit empty entirely. If not, you need to determine what "empty" means conceptually for your class, and return someting accordingly.
Now, we can illustrate how they interact. When you redefine paren, you are in control of size, which is how the default isempty will determine what to return for your class. So long as your empty() method returns <an instance of your class where size returns at least one zero dimension>, you will satisfy the requirements.
I do not know what your array-like object, CustomClass does to store the underlying array information. But you could have empty return an empty array of that underlying type however it gets stored. You can see an example of this called ArrayWithLabel in the RedefinesParen help page under "Examples." Alternatively, your class might store the dimensions in an entirely different variable from the data. You could return an instance with no data aside from a dimension of 0x0 or some other "empty" size value.
-----
A completely different question you asked was about "Error using class. Not enough input arguments."
This is because arr.prop returns a comma-separated list of 0 elements (see generating a comma-separated list section). In other words, it has 0 output arguments. class() called with zero arguments will always print this error. Because your first custom class overloads empty, it returns one input argument, which class() knows what to do with.
参考
カテゴリ
Help Center および File Exchange で Construct and Work with Object Arrays についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!