|
From: | Robert T. Short |
Subject: | Re: OOP load update |
Date: | Wed, 06 May 2009 10:12:20 -0700 |
User-agent: | Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.21) Gecko/20090402 SeaMonkey/1.1.16 |
Judd do you remember the attached emails? The context was this: I had suggested that I should call the class constructor, John asked the question "what about constructors with parameters" so I went and played with it. I need to remember what I did, but if you don't do things just right you get a nastygram like
Warning: Could not determine the fields for class Foo by calling the constructor with no input arguments. The object a has been converted to a structure. To eliminate the conversion create an object of class Foo before calling LOAD. So, what were the conditions under which you got the message?Whatever, I think this is pretty easy to fix and was already in the plan. Basically the load algorithm goes like this
if there might be an inheritance issue then if there is no entry in the exemplar table then execute the class constructor to create an exemplar table entry if executing the class constructor failed, return the broken class use the exemplar table to reconstruct the inheritanceif there is an inconsistency in the inheritance structure return the broken class
if there is no inheritance problem execute the user's loadobj method check the class for consistency with the exemplar table entry if inconsistent, return the broken class else return the classThe only difference between the above and what is done now is that I don't currently execute the class constructor.
MATLAB returns a struct, not the broken class but as of now I don't see how to return a struct without some kludge. There is really no difference between the broken class and the correct class except a warning message and the fact that methods and inheritance may not work properly. Once the struct(obj) function works properly the struct can be obtained from the broken class easily. This isn't totally MATLAB compatible, but not bad, and fixing broken classes isn't something that is a normal activity. The loadobj function is really designed to patch up inconsistencies between saved classes and the current class definitions. I don't see any facilities in MATLAB for the loadobj function to fix inheritance issues, but I could make something like that in octave.
There are actually several items in the last set of emails that I need to absorb. Hopefully this weekend....
Bob -- Robert T. Short PhaseLocked Systems Judd Storrs wrote:
I'm pretty sure the constructor is called if Matlab doesn't have a class definition. Suppose:@FooBar/FooBar.m: function obj = FooBar() disp('Hello!'); obj.data = 'Baz'; obj = class(obj, 'FooBar'); Then at least in Matlab R14 (7.0.1) (I've edited whitespace): Matlab Session 1: >> obj1 = FooBar() Hello! obj1 = FooBar object: 1-by-1 >> save('test.mat','obj1')>> obj2 = FooBar() Hello!obj2 = FooBar object: 1-by-1 >> save('test2.mat','obj2') >> exit Matlab Session 2: >> load test.mat Hello! >> load test2.mat >>As you see in the second session, matlab does execute the constructor the first time it encounters the FooBar class, but once it knews the class structure, it didn't need to call the constructor again.--judd
--- Begin Message ---Subject: Re: OOP and load/save I was playing around in Matlab R2007b. Date: Thu, 23 Apr 2009 11:24:25 -0400
Create
@Foo/Foo.m
function f = Foo()
d2/@Foo/Foo.m:
Warning: Could not determine the fields for class Foo by calling the
constructor with no input arguments. The object a has been
converted to a structure. To eliminate the conversion create
an object of class Foo before calling LOAD.On Thu, Apr 23, 2009 at 10:09 AM, Robert T. Short <address@hidden> wrote:
I tried a bunch of stuff last night including the argument case. MATLAB gets it right every time. I walked through a .mat file with both the aggregation and inheritance case and there is nothing in the file that tells which it is, so somehow MATLAB figures it out from the sources or something. Somebody over at the Mathworks is smarter than I am.John W. Eaton wrote:
On 22-Apr-2009, Robert T. Short wrote:
| John W. Eaton wrote:
| > On 22-Apr-2009, Robert T. Short wrote:
| >
| > | I hadn't thought of that. Good question and the answer is that there is | > | no guarantee. In fact, some of my "real" classes require arguments. | > | | > | I think I have to go back to the drawing board on this. | >
| > I suggest that you try saving and reloading one of those classes
| > (preferably one with a parent class) in Matlab and see what happens.
| > Does it work?
| >
| > jwe
| >
| >
| > | Yes it works, but it occurs to me that I hadn't checked to see if all | the DETAILS worked right.
Did you try it to see what happens when a constructor requires an
argument?
jwe
I doubt I will really be able to spend enough time before the weekend to make a real impact, but I will eyeball your diff and the stuff you sent out yesterday.
I think I have a workable short term solution. I will type that up as soon as I can. I can get that implemented and at least we will have a complete solution, if a little imperfect.
Bob
--- End Message ---
--- Begin Message ---Subject: Re: OOP and load/save Taking the example further change @Foo/Foo.m to Date: Thu, 23 Apr 2009 11:46:23 -0400
function f = Foo(f)
f = class(f, 'Foo');
Then in matlab:
>> load test.mat
Warning: Could not determine the fields for class Foo by calling the
constructor with no input arguments. The object a has been
converted to a structure. To eliminate the conversion create
an object of class Foo before calling LOAD.
>> f.dataelement = 'I am Foo';
>> f = Foo(f);
>> load test.mat
>> bar
bar =
Foo object: 1-by-1
Ok, restart matlab
>> f.notdataelement = 'I am not Foo';
>> f = Foo(f);
>> load test.mat
Warning: Fields of object 'bar' do not match the current constructor
definition for class 'Foo'. The object has been converted
to a structure.
--judd
--- End Message ---
--- Begin Message ---Subject: Re: OOP and load/save Date: Thu, 23 Apr 2009 12:01:54 -0400 On Thu, Apr 23, 2009 at 11:46 AM, John W. Eaton <address@hidden> wrote:On 23-Apr-2009, Judd Storrs wrote:OK. Is that information separate from any objects that are in the
| So, I think Matlab keeps an internal memory of each class structure.
| Probably the first time a class of a specific type is created, Matlab
| remembers the member information. If Matlab doesn't have member information
| it calls the constructor with no arguments. I'll do some more testing to
| verify.
symbol table? I.e., does "clear all" followed by loading the file
result in the error message when there is no valid constructor?
Clear all doesn't seem to clear the class memory
>> bar = Foo()
bar = Foo object: 1-by-1
>> save test.mat bar
>> clear all
>> load test.mat
>> class(bar)
ans = Foo
Outside of matlab, break @Foo/Foo.m
>> clear all
>> load test.mat
>> class(bar)
ans =Foo
>> clear all
>> bar2 = Foo()
bar2 = []
>> load test.mat
>> class(bar)
ans = FooWhat happens if you modify the constructor (for example, to add or
remove a field from the class structure) when Matlab is running and
already has some object(s) created using the previous constructor?
Does that generate an error?
Reset @Foo/Foo.m
function Foo ()
f.dataelement = 'I am Foo';
f = class(f,'Foo');
>> bar = Foo()
bar = Foo object: 1-by-1
>> struct(bar)
ans = dataelement: 'I am Foo'
Outside matlab add a new field to @Foo/Foo.m:
function Foo ()
f.dataelement = 'I am Foo';
f.newelement = 'I am even more Foo';
f = class(f,'Foo');
>> bar2 = Foo()
??? Error using ==> class
Number of fields for class Foo cannot be changed without clear classes.
Error in ==> Foo.Foo at 4
f = class(f,'Foo');
>> clear classes
>> bar2 = Foo()
bar2 = Foo object: 1-by-1
>> class(bar)
??? Error using ==> bar at 48
Not enough input arguments.
>> struct(bar2)
ans =
dataelement: 'I am Foo'
newelement: 'I am even more Foo'
>> struct(bar)
??? Error using ==> bar at 48
Not enough input arguments.
>> help clear
...
CLEAR CLASSES is the same as CLEAR ALL except that class definitions
are also cleared. If any objects exist outside the workspace (say in
userdata or persistent in a locked m-file) a warning will be issued and
the class definition will not be cleared. CLEAR CLASSES must be used if
the number or names of fields in a class are changed.
...
--judd
--- End Message ---
[Prev in Thread] | Current Thread | [Next in Thread] |