第二十三章 Caché 实施动态调度

第二十三章 Caché 动态调度简介(动态分配)

Caché类可以包括对所谓的动态调度的支持。如果正在使用动态调度,并且程序引用的属性或方法不是类定义的一部分,则会调用尝试解析未定义的方法或属性的方法(称为调度方法)。例如,动态调度可以为未定义的属性返回值,也可以为未实现的方法调用方法。动态分配,因为它不会出现在类描述符中,并且直到运行时才会解析。

Caché提供了许多可以实现的分派方法。每种方法都尝试解析在不同情况下丢失的元素。

如果实现调度方法,则具有以下效果:

  • 在应用程序执行期间,如果Caché遇到不属于已编译类的元素,它将调用分派方法来尝试解析遇到的元素。

  • 使用该类的应用程序代码不会执行任何特殊操作来实现这一点。Caché自动检查是否存在分派方法,如果该方法存在,则调用它。

实施动态调度的方法内容

作为应用程序开发人员,可以控制调度方法的内容。它们中的代码可以是实现类尝试解析的方法或属性所需的任何代码。

用于动态分派的代码可能包括尝试根据相同范围、包、数据库、相同文件系统上的其他类或任何其他标准来定位方法。如果分配方法提供一般情况,建议该方法还为此操作创建某种类型的日志,以便记录包括此一般解决方案的任何持续操作。

例如,%DispatchClassMethod()的以下实现允许应用程序用户调用方法来执行预期的任何操作:是否有包含此常规解决方案的任何连续操作的记录。

ClassMethod %DispatchClassMethod(Class As %String, Method As %String, args...)
{
    WRITE "应用程序已尝试调用以下方法: ",!,!
    WRITE Class,".",Method,!,!
    WRITE "此方法不存在.",!
    WRITE "输入要调用的类和方法的名称",!
    WRITE "或者同时按Enter键退出应用程序.",!,!


    READ "类名(格式为“Package.Class”): ",ClassName,!
    READ "方法名: ",MethodName,!
    
    IF ClassName = "" && MethodName = "" {
        // 如果需要返回值,则向调用方返回空字符串
        QUIT:$QUIT "" QUIT
    } ELSE {
        // 选中$QUIT可确保返回值
        IF $QUIT {
            QUIT $CLASSMETHOD(ClassName, MethodName, args...)
        } ELSE {
            DO $CLASSMETHOD(ClassName, MethodName, args...)
            QUIT
        }
    }
}

通过将此方法包含在作为应用程序中所有类的次要父类的类中,可以在应用程序范围内建立对不存在的类方法的调用的处理。

返回值

所有调度方法都没有指定返回值。这是因为每个都应该提供与最初创建分派需求的调用类型相同的输出。

如果分派方法不能解析方法或属性,它可以使用$ZUTIL(96,3)抛出或错误-或者其他任何合适的错误。

DHC-APP>d ##class(PHA.OP.MOB.Test).%DispatchClassMethod("PHA.OP.MOB.Test","TestGetSet")
应用程序已尝试调用以下方法:
 
PHA.OP.MOB.Test.TestGetSet
 
此方法不存在.
输入要调用的类和方法的名称
或者同时按Enter键退出应用程序.
 
类名(格式为“Package.Class”): PHA.OP.MOB.Test                                         方法名: TestGetSet                                                                 three.nameGet(): yaoxin1
three.name: yaoxin1

关于动态调度方法的探讨

%DispatchMethod()

此方法实现未知的方法调用。其语法为:

Method %DispatchMethod(Method As %String, Args...)

其中,它的第一个参数是被引用方法的名称,第二个参数是保存传递给原始方法的所有参数的数组。由于参数的数量及其类型可能因解析的方法而异,因此%DispatchMethod()中的代码需要正确处理它们(因为类编译器不能对类型做出任何假设)。Args…语法可以灵活地处理此问题。

由于%DispatchMethod()尝试解析与类关联的任何未知实例方法,因此它没有指定的返回值;如果成功,它将返回一个值,该值的类型由要解析的方法以及调用方是否需要返回值确定。

%DispatchMethod()还可以解析未知的多维属性引用,即获取属性的值。但是,动态调度仅支持直接多维属性引用。不支持 D A T A DATA、 ORDER和$QUERY,也不支持带有变量列表的SET命令。

%DispatchClassMethod()

此方法实现未知的类方法调用。其语法为:

ClassMethod %DispatchClassMethod(Class As %String, Method As %String, Args...)

其中,它的前两个参数是被引用类的名称和被引用方法的名称。它的第三个参数是保存传递给原始方法的所有参数的数组。由于参数的数量及其类型可能因解析的方法而异,因此%DispatchClassMethod()中的代码需要正确处理它们(因为类编译器不能对类型做出任何假设)。。Args…。语法可以灵活地处理此问题。

由于%DispatchClassMethod()尝试解析与类关联的任何未知类方法,因此它没有指定的返回值;如果成功,它将返回一个值,该值的类型由要解析的方法以及调用方是否需要返回值确定。

%DispatchGetProperty()

此方法获取未知属性的值。其语法为:

Method %DispatchGetProperty(Property As %String)

其中其参数是引用的属性。由于%DispatchGetProperty()尝试解析与类关联的任何未知属性,因此它没有指定的返回值;如果成功,它将返回一个类型为正在解析的属性的值

%DispatchSetProperty()

此方法设置未知属性的值。其语法为:

Method %DispatchSetProperty(Property As %String, Value)

其中,其参数是被引用属性的名称和要为其设置的值。

%DispatchSetMultidimProperty()

此方法设置未知多维属性的值。其语法为:

Method %DispatchSetMultidimProperty(Property As %String, Value, Subs...)

其中,它的前两个参数是被引用属性的名称和要为其设置的值。第三个参数Subs是一个包含下标数值的数组。SUBS具有指定下标数量的整数值,SUBS(1)具有第一个下标的值,SUBS(2)具有第二个下标的值,依此类推。如果没有给出下标,则子是未定义的。

动态调度仅支持直接多维属性引用。不支持$DATA$ORDER$QUERY,也不支持带有变量列表的SET命令。

注意:注意没有%DispatchGetMultidimProperty()调度方法。这是因为多维属性引用与方法调用相同。因此,这样的引用调用%DispatchMethod(),它必须包含区分方法名称和多维属性名称的代码。

发布了29 篇原创文章 · 获赞 29 · 访问量 2181

猜你喜欢

转载自blog.csdn.net/yaoxin521123/article/details/105305401