跳转至

通过开发静态方法简化代码库和对象访问

原文链接: https://www.nv5geospatialsoftware.com/Learn/Blogs/Blog-Details/simplifying-code-libraries-and-object-access-by-developing-static-methods

19482 对此文章评分:

暂无评分

通过开发静态方法简化代码库和对象访问

Anonym 2014年2月20日 星期四

IDL 8.3 的另一个新特性是能够在类上创建静态方法。静态方法是一种可以在类外部调用而无需类实例的方法,既可以是过程方法也可以是函数方法。它们可以使用"点"语法调用,从外部看,它们的工作方式与常规的 IDL 例程或函数完全相同。静态方法有许多潜在的用途。本文将讨论对库例程进行分组的方法,并讨论如何方便地访问单例对象操作。要将方法定义为静态方法,请在方法的 COMPILE_OPT 语句中添加'static'关键字。

静态方法通过允许将例程按类别分组,使得代码库的开发和维护变得更加容易。IDL 已经将其部分内置类方法设置为静态方法,例如 Clipboard。

在 IDL 8.3 之前,每个用户编写的辅助例程要么需要放在单独的文件中,要么需要在可以使用之前编译其所在的完整文件。以下是一个包含多个辅助例程的 IDL 8.3 之前版本的文件示例:

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

为了调用 helper1 或 helper2,调用者必须首先调用 RESOLVE_ROUTINE, 'helper_routines';否则会发生错误。然而,通过将这些例程分组为静态方法,只要文件在 IDL 的路径中,IDL 将在需要时自动编译这些方法,用户无需手动解析它们。以下是将辅助例程分组到一个类中的示例:

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

出于例程分组的目的,永远不需要创建该类的实例。因此,此类不需要 Init 方法;仅需要类定义。

要调用其中一个例程,请使用以下语法:

helper_class.helper1

然后 IDL 将编译并运行该例程。将这些辅助例程分组不仅提供了共用类别名称的便利,还有助于防止命名空间冲突。例如,您可以创建第二个辅助类,例如 'helper_class2',它也有一个名为 'helper1' 的方法,由于这两个方法属于不同的类,它们之间不会发生冲突。

静态方法的第二个实际用途是提供对单例类的便捷访问。在此示例中,有一个名为 'IDLDataPoint' 的类,并且在整个应用程序中只会实例化其中一个此类。该类存储在应用程序范围的公共块中,其属性和方法需要在应用程序的许多部分中使用。

在 IDL 8.3 之前,任何需要访问此类的例程都必须从公共块中检索它。然而,在 IDL 8.3 中,可以使对象的方法变为静态方法(这包括 GetProperty 和 SetProperty),从而允许在不需要直接引用对象的情况下调用它们,并且获取引用的工作只能在方法内部完成。实现此目的的主要技巧是对 self 调用 OBJ_VALID,然后递归地调用方法。以下是 IDLDataPoint 类的示例:

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

使用以下例程创建类并将其存储在公共块中:

PRO create_datapoint_class

COMMON IDLDataPoint_Common, dataPointObj

  dataPointObj = OBJ_NEW('IDLDataPoint')

END

现在,无需获取 IDLDataPoint 类的实例,您就可以执行所有操作,就像拥有实例一样。以下是一些展示属性访问和使用方法的代码:

PRINT, IDLDataPoint.NAME

IDL 打印:

IDL Data Point

PRINT, IDLDataPoint.VALUE

IDL 打印:

5

IDLDataPoint.VALUE=6

result = IDLdataPoint.MultiplyValue(4)

PRINT, result

IDL 打印:

24

感谢阅读。希望这些信息对您有所帮助。

从太空统计鲸鱼数量 社交媒体与图像分析