在侦听器中创建对象(某些类)(第二部分)

时间:2015-08-15 15:14:28

标签: oop events dm-script

我做了一些关于此问题的other question,反应很好,但是我试错了一个听众的例子:

是否有人会测试此代码并解释为什么它找不到EVENT_ONE类?

void functionONE(){
    result("\n dentro de la FUNCION ONE")
}


class EVENT_ONE : object{

    void accionONE(object self){
        result("\n dentro de accionONE()")
    }

    EVENT_ONE(object self) result("\n EVENT_ONE creado")
    ~EVENT_ONE(object self) result("\n EVENT_ONE destruido")
}

class KEY_TWO : object{

    number evento
    object o

    void almacenaEventoTWO(object self, number pulsacion) evento = pulsacion

    number accionTWO(object self, ImageDisplay disp, object keydesc){
        number control=0

        Result("\n key:"+keydesc.GetKeyDescriptor())
        Result(" ("+keydesc.GetDescription()+")") 

        If ( keydesc.MatchesKeyDescriptor("esc")){
            result("\n has pulsado escape")
            control=1
            disp.ImageDisplayRemoveKeyHandler(evento)

            o = alloc(EVENT_ONE)
            //number idObjecto2 = disp.ImageDisplayAddEventListener( o,     "accionONE" )
            o.accionONE()

        }
        return control
    }

    KEY_TWO(object self) result("\n KEY_TWO creado")
    ~KEY_TWO(object self) result("\n KEY_TWO destruido")
}


void main(){
    image img = getFrontImage()
    showimage(img)
    imageDisplay imgDisp = img.imageGetImageDisplay(0)

    object controlFinal = Alloc(KEY_TWO)
    number idControlFinal = imgDisp.ImageDisplayAddKeyHandler( controlFinal,     "accionTWO" )
    controlFinal.almacenaEventoTWO(idControlFinal)
}
main()

必须在键盘监听器(类KEY_TWO)的桌面上放置任何图像。在这个课程中,当我按任意键,打印它,如果你按下" esc",销毁关键监听器并找到错误("未找到EVENT_ONE类")。

另一方面,是否可以调用" functionONE"从类KEY_TWO或EVENT_ONE ??

很抱歉打扰但是我没有发现错误。

谢谢和问候。塞尔吉奥

2 个答案:

答案 0 :(得分:1)

Mike对于脚本代码保持正确"可用"只要脚本解析器持有。但是,更好的解决方案是在KEY_TWO类的构造函数中(或在主脚本中调用的初始化方法中)分配第二个对象。在此阶段,代码仍然可用。所以你上面的脚本变成了:

class EVENT_ONE : object{

    void accionONE(object self){
        result("\n dentro de accionONE()")
    }

    EVENT_ONE(object self) result("\n EVENT_ONE creado")
    ~EVENT_ONE(object self) result("\n EVENT_ONE destruido")
}

class KEY_TWO : object{

    number evento
    object o

    void almacenaEventoTWO(object self, number pulsacion){
        evento = pulsacion
    }

    number accionTWO(object self, ImageDisplay disp, object keydesc){
        number control=0

        Result("\n key:"+keydesc.GetKeyDescriptor())
        Result(" ("+keydesc.GetDescription()+")") 

        If ( keydesc.MatchesKeyDescriptor("esc")){
            result("\n has pulsado escape")
            control=1
            disp.ImageDisplayRemoveKeyHandler(evento)

            //o = alloc(EVENT_ONE)  // DO NOT ALLOCATE HERE - THE CODE IS NO LONGER AVAILABLE

            o.accionONE()
        }
        return control
    }

    KEY_TWO(object self) 
    {
        result("\n KEY_TWO creado")
        o = alloc(EVENT_ONE) // ALLOCATE HERE - THE CODE IS STILL AVAILABLE
    }
    ~KEY_TWO(object self) result("\n KEY_TWO destruido")

    // ALTERNATIVELY: Have a Init-method and alloacte here. This method is called (from the main script)
    // while all code is still available. Return the object self just to be able to "pipe-line" the Init call
    object Init(object self) {
        // o = alloc(EVENT_ONE) // ALTERNATIVE ALLOCATE HERE - THE CODE IS STILL AVAILABLE
        return self
    }
}


void main(){
    image img = getFrontImage()
    showimage(img)
    imageDisplay imgDisp = img.imageGetImageDisplay(0)

    object controlFinal = Alloc(KEY_TWO).Init() // Call INIT method
    number idControlFinal = imgDisp.ImageDisplayAddKeyHandler( controlFinal,     "accionTWO" )
    controlFinal.almacenaEventoTWO(idControlFinal)
}
main()

至于全局功能:我建议你完全避免全局方法和变量。 OOC的想法是将所有代码封装在对象中。

最后,还可以选择在main方法中分配所有对象,并将它们作为参数传递给其他对象。这允许f.e.让多个其他对象访问相同的对象。但是有一个警告:小心对象不要相互抓住"彼此"或者他们不能从记忆中释放出来。 (这可以通过使用ObjectID和命令GetScriptObjectFromID来避免。有关详细信息,请参阅 scripting-> Objects 一章中关于弱引用的F1帮助文档。 。)

这种结构的一个例子:

class CCommon
{
    number v
    CCommon( object self ) { result("Created CCommon ID:"+self.ScriptObjectGetID()+"\n"); }
    ~CCommon( object self ) { result("Destructed CCommon ID:"+self.ScriptObjectGetID()+"\n"); }
    number GetV(object self ) { return v; }
    object SetV(object self, number val){ v=val; return self; }
}

class COne
{
    object co
    object init( object self, object common ) { co=common; return self; }
    object double( object self ) { co.SetV( co.GetV() * 2 ); return self; }
}

class CTwo
{
    object co
    object init( object self, object common ) { co=common; return self; }
    object AddOne( object self ) { co.SetV( co.GetV() + 1 ); return self; }
}

void main()
{
    object c = Alloc(CCommon).SetV(0)
    result("\n Initial:" + c.GetV() + "\n" )
    object o1 = Alloc(COne).Init(c)
    object o2 = Alloc(CTwo).Init(c)
    for (number i=0;i<10;i++)
    {
        o2.AddOne()
        result(" After +1: " + c.GetV() + "\n" )
        o1.Double()
        result(" After x2: " + c.GetV() + "\n" )
    }
}
main()

答案 1 :(得分:0)

执行的DM脚本文件中的类定义仅在执行该脚本期间有效。当用户为您的侦听器输入击键时,您的主要功能已完全执行,因此EVENT_ONE的类定义不再有效。如果将EVENT_ONE和KEY_TWO类的实现拆分为单独的文件,然后将该文件安装为脚本库,则代码将起作用。这样,类定义在DM会话的整个生命周期内都保持有效。