Simplifying Code Libraries and Object Access By Developing Static Methods
Anonym
Another new feature in IDL 8.3 is the ability to create static methods on classes. A static method is a method, either a procedure method or function method, which can be called from outside the class without needing an instance of the class. They can be called using the "dot" syntax, and, from the outside, they work just like regular IDL routines or functions. There are a number of potential uses for static methods. This article will discuss grouping library routines and will also discuss easy access to singleton object operations. To define a method as static, add 'static' to the method's COMPILE_OPT statement.
Static methods can make code libraries much easier to develop and manage by allowing routines to be grouped into categories. IDL has already made some of its built-in class methods static, such as Clipboard.
Prior to IDL 8.3, every user-written helper routine either needed to be in its own file or else the full file in which it is located needed to be compiled before it could be used. Here is an example of a pre-IDL8.3 file that contains multiple helper routines:
PRO helper1
PRINT, 'Helper 1 was called.'
END
PRO helper2
PRINT, 'Helper 2 was called.'
END
PRO helper_routines
; This is a placeholder routine.
END
In order to call either helper1 or helper2, the caller must first call RESOLVE_ROUTINE, 'helper_routines'; otherwise an error would occur. By grouping these routines into static methods, however, IDL will automatically compile the methods when needed, provided that the file is in IDL's path, and the user does not need to manually resolve them. Here is an example of grouping the helpers into a class:
PRO helper_class::helper1
COMPILE_OPT static
PRINT, 'Helper 1 was called'
END
PRO helper_class::helper2
COMPILE_OPT static
PRINT, 'Helper 2 was called'
END
PRO helper_class__define
!null = {helper_class, $
INHERITS IDL_Object}
END
For purposes of grouping routines, there will never be a need to create an instance of the class. Therefore, this class does not need an Init method; only the class definition is needed.
To call one of these routines, use the following syntax:
helper_class.helper1
and IDL will compile and run the routine. Not only does grouping these helper routines offer convenience of a common category name, it also helps prevent namespace conflicts. For example, you could create a second helper class, such as 'helper_class2' that also has a method called 'helper1', and there would not be a conflict between the two methods because they are part of different classes.
A second practical use for static methods is to provide easy access to singleton classes. In this example, there is a class called 'IDLDataPoint', and only one of these classes is ever going to be instanciated throughout the application. This class is stored in an application-wide common block, and its properties and methods need to be used in many parts of application.
Prior to IDL 8.3, any routine that needed to access this class must retrieve it out of the common block. However, in IDL 8.3, the object's methods can be made static (this includes GetProperty and SetProperty), allowing them to be called without having a direct reference to the object, and the only place where the work of retrieving the reference can be done within the method. The main trick to doing this is to call OBJ_VALID on self and then call the method recursively. Here is an example of the IDLDataPoint class:
FUNCTION IDLDataPoint::Init
self.name = 'IDL Data Point'
self.value = 5L
RETURN, 1
END
PRO IDLDataPoint::GetProperty, NAME=name, VALUE=value
COMPILE_OPT static
IF ~OBJ_VALID(self) THEN BEGIN
COMMON IDLDataPoint_Common, dataPointObj
dataPointObj.GetProperty, NAME=name, VALUE=value
RETURN
ENDIF
IF ARG_PRESENT(name) THEN BEGIN
name = self.name
ENDIF
IF ARG_PRESENT(value) THEN BEGIN
value = self.value
ENDIF
END
PRO IDLDataPoint::SetProperty, NAME=name, VALUE=value
COMPILE_OPT static
IF ~OBJ_VALID(self) THEN BEGIN
COMMON IDLDataPoint_Common, dataPointObj
dataPointObj.SetProperty, NAME=name, VALUE=value
RETURN
ENDIF
IF N_ELEMENTS(name) GT 0 THEN BEGIN
self.name = name
ENDIF
IF N_ELEMENTS(value) GT 0 THEN BEGIN
self.value = value
ENDIF
END
FUNCTION IDLDataPoint::MultiplyValue, multiplier
COMPILE_OPT static
IF ~OBJ_VALID(self) THEN BEGIN
COMMON IDLDataPoint_Common, dataPointObj
RETURN, dataPointObj.MultiplyValue(multiplier)
ENDIF
RETURN, multiplier * self.value
END
PRO IDLDataPoint__Define
!null = {IDLDataPoint, $
inherits IDL_Object, $
name:'', $
value:0L}
END
Create the class and store it in the common block with this routine:
PRO create_datapoint_class
COMMON IDLDataPoint_Common, dataPointObj
dataPointObj = OBJ_NEW('IDLDataPoint')
END
Now, without ever needing to get the IDLDataPoint class’s instance, you can do everything with this object that you could if you had an instance. Here is some code that shows property access and using a method:
PRINT, IDLDataPoint.NAME
IDL prints:
IDL Data Point
PRINT, IDLDataPoint.VALUE
IDL prints:
5
IDLDataPoint.VALUE=6
result = IDLdataPoint.MultiplyValue(4)
PRINT, result
IDL prints:
24
Thank you for reading. I hope this information is helpful.