MATLAB Answers

Translated by

このページのコンテンツは英語から自動翻訳されています。自動翻訳をオフにする場合は「<a class="turn_off_mt" href="#">ここ</a>」をクリックしてください。

1

Given an instance of a class (without knowing class name), how to call the constructor?

Martin Vatshelle さんによって質問されました 2019 年 3 月 18 日
最新アクティビティ Adam
さんによって コメントされました 2019 年 3 月 18 日
I have made a minimal example trying to implement a clone method
classdef Person
properties
name;
id;
end
methods
% Constructor
function person = Person(name)
person.name = name;
person.id = Person.getID();
end
% simple function
function name = getName(person)
name = person.name;
end
% Simple method where Constructor is called
function person = clone(person)
%want to call Constructor so even clones get unique ID
person = Person(person.name);
end
end
methods (Static)
%assign personal id (simplified version)
function id = getID()
persistent max_personal_id;
if(isempty(max_personal_id))
max_personal_id = 0;
end
max_personal_id = max_personal_id+1;
id = max_personal_id;
end
end
end
Now I try to extend the class to another class with same constructor arguments, without having to reimplement the clone method
classdef FireMan < Person
methods
% Constructor
function person = FireMan(name)
person@Person(name);
end
function name = getName(person)
name = ['FireMan ',person.name];
end
end
end
But this does not give wanted functionality of the clone method as it
p = FireMan('Sam');
p.getName()
ans =
'FireMan Sam'
p.clone.getName()
ans =
'Sam'
This happens of course because I call the Person constructer in the clone method and not the Fireman Constructor
I could of course add something like this to every subclass.
function person = construct(~,name)
person = FireMan(name);
end
But I wonder if I could avoid changes in the subclass.

  0 件のコメント

サインイン to comment.

3 件の回答

回答者: Sean de Wolski
2019 年 3 月 18 日
 採用された回答

Might you be interested in inheriting from matlab.mixin.Copyable which gives you a copy method?

  4 件のコメント

Unless you implement your own copyElement(), a protected method of the class, which generates a new ID.
As a straight answer to your question: look at metaclass(), it will hold the information you need on the constructor and you can call str2func() to generate an evaluator function for the Constructor.
Or just
str2func( class( p ) )
should also work.
This last was much easier to understand and can be applied in many other cases than just copying the object so this is exactly what I needed.
Thank you!

サインイン to comment.


回答者: Guillaume
2019 年 3 月 18 日

As Sean said, you may want to inherit from matlab.mixin.Copyable instead of implementing your own cloning interface. However, this would force your class to be a handle class.
Regardless, if you want just one copyElement/clone method, then you need to use reflection to know the actual class of the object you're cloning. You'll have to use eval or feval to invoke the correct constructor. It's one of the rare cases where eval makes sense:
% Clone (or copyElement) method within the base class
function person = clone(person)
assert(isa(person, 'Person'), 'input must be of class Person or one of its derived class');
person = feval(class(person), person.name); %invoke actual constructor of the class (same name as the class)
end
Also, note that your clone method is flawed. It only works with scalar inputs. If your class is not designed to work with arrays of Person, then you need to document and prevent that (protected horzcat, vertcat and cat which error). matlab.mixin.Copyable hides the troubles of dealing with class arrays (CopyElement is invoked for each element of the array). If you allow arrays of persons, you may also want to look at matlab.mixin.Heterogeneous

  2 件のコメント

Thanks, this is a good solution.
I know my Class don't work with arrays, but it was an attempt to make a minimal working example and not really the code I am working on.
My real code does extend matlab.mixin.Heterogeneous
I guess this is fairly equivalent to
str2func( class( p ) )
As suggested by Sean
Yes, it's equivalent to str2func. It's probably more concise with feval.

サインイン to comment.


回答者: Adam
2019 年 3 月 18 日

Since your class doesn't inherit from handle the assignment operator will give you a copy of the correct class. However, this won't call the constructor so you would not get a new id. However, if the id is the only thing you want to change you could just change your clone function to
% Simple method where Constructor is called
function newPerson = clone(person)
%want to call Constructor so even clones get unique ID
newPerson = person;
newPerson.id = Person.getID( );
end

  2 件のコメント

Thanks for your help, I know this is one way to do it.
My problem with this is that I duplicate the code of the constructor.
clone is just one example how one might reuse the constructor, if one have many different functions calling the constructor I feel this practice makes it a bit harder to maintain the code.
Well, I would probably put my constructor code into an initialise() function and call that where I needed, but I have also used the str2func appraoch discussed above.

サインイン to comment.



Translated by