octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: OOP load update


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

Hmmm. Seems that Judd is correct. If the constructor is available and if it has no parameters, then the load works even if MATLAB doesn't have a current class structure.

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 inheritance
if 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 class

The 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 Date: Thu, 23 Apr 2009 11:24:25 -0400 I was playing around in Matlab R2007b.

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:
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 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.

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 Date: Thu, 23 Apr 2009 11:46:23 -0400 Taking the example further change @Foo/Foo.m to

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:

| 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.

OK.  Is that information separate from any objects that are in the
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 = Foo


What 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 ---

reply via email to

[Prev in Thread] Current Thread [Next in Thread]