Method call
2004/01/03 : virtual method call is now implemented in series of oop_call functions, which are way better than oop_do. This part of the document will be updated in the future.
Method call is impolemented in a function oop_do. It accepts a path to the datafolder, method name, and arguments converted to a string. E.g.
oop_do("root:foo", "bar", "()")
The class where foo belongs or the parent classes of foo must have bar method. A method of a class is a function with a name classname_method.
method = function classname_methodname(...)
oop_do first look for a function with the name classname_method in the class which the object belongs, if it fails then it looks for the method in parent classes. If it find an appropriate function, it set current datafolder to the object's datafolder and it calls the method function using execute.
Function oop_do(path, method, args)
string path, method, args
variable count
string df = getdatafolder(1)
if (! datafolderexists(path))
print "object:",path," does not exists."
return -1
endif
setdatafolder $(path)
SVAR class = class
if (exists("class") != 2)
print path, " is not a class instance!", ", method = ", \
method, "args=", args
return 0
endif
wave /t parents= parents
// get function name
string fname = "";
if (exists( class+"_"+method) == 6)// first check "classname+method"
fname = class+"_"+method;
else
// no function w/ "classname+method" check "parentname+method"
for (count =numpnts(parents)-1; count > -1; count -= 1)
if (exists(parents[count]+"_"+method) == 6)
fname = parents[count]+"_"+method
break
endif
endfor
endif
if (cmpstr(fname, "")==0)
print "No method exists: obj=", path, " class=", class, " \
method=", method, args
setdatafolder df
return -1
endif
// call method
Execute(fname+args)
if (datafolderexists(df))
setdatafolder df
else
setdatafolder $("root:")
endif
return 0
End
You have to pass arguments in a string form. This is really awkward, cumbersome erroneous and unreadable. But I couldn't find a better way, so I usually tend to pass no argument (just pass "()") and set members (using oop_set_* functions) before calling oop_do.
An alternative to the above solution is described in OOP file (oop_getFname(obj, method)). oop_getFname returns function reference, so you don't have to encode arguments in a string and you can get return value. But since Igor doesn't allow variable number of arguments (am I wrong?), I couldn't put the whole sequence in one function, so every time you want to call a method, you have to
- get function ref with oop_getFname
- set current datafolder to the object's datafolder
- call the method function
- restore current datafolder
which is probably more cumbersome than the first one.
Accessor
From method
Since oop_do sets the current datafolder to the object's datafolder before method call. Method functions can access members using following igor definitions.
- SVAR strmembername (for string member access)
- NVAR varmembername (for variable member access)
- wave wavename
- wave /t textwavename
From outside
- oop_get_s(path, name)
- oop_get_v(path, name)
- oop_set_s(path, name, value)
- oop_set_v(path, name, value)
Or you can just use SVAR, NVAR with fullpath. e.g.
SVAR foostr1 = $("root:foo:str1")
etc.
Pitfalls
- Not suited for small & numerous object (many datafolders)
- oop_do : not suited for frequent call (like in huge "for" loop)
- oop_do : requires an argument converted to a string (better use accessors)
But completely OK for opposite cases (infrequent call, no argument, small number of objects, ...).
Reserved Names
| class | string | keeps class name |
| parents | text wave | keeps parents' class names |
| path | string | path (in a harddisk) where the object will be saved |
| lpath | string | path (in a harddisk) where the object is loaded from |
| id | string | id (created from path to the datafolder) of the object |