1

我们想为三星 Groovy SmartThings 实现一个基础设施。基础设施的主要部分当然是使用相应的方法为每个设备实现不同的类。例如,对于锁的设备,我们假设我们有一个带有 lock() 和 unlock() 方法的锁类。这里的问题是我们在 Groovy 中的一个 SmartThings 应用程序中拥有这部分代码:

def presence(evt)
{
    if (evt.value == "present") {
            //Somecode
            lock1.unlock()
    }
    else {
            //Somecode
            lock1.lock()
    }
}

所以很可能,lock1 是类 lock 的对象,而 lock() 和 unlock() 是该类的方法。事情是这样的:使用 lock1[0].unlock() 命令解锁门锁编号 #0,但使用 lock1.unlock() 命令解锁所有门锁。

这里的问题是类是如何创建的?如果 lock1 是一个对象列表,我们如何才能拥有 lock1.unlock() 之类的命令。

这里的重点是两个对象都应该具有相同的名称 lock1,并且这两个方法都是同一个名为 lock() 的方法。

先感谢您。

4

2 回答 2

1

这里要看到的“问题”是Groovy中的(隐式)扩展运算符。

表达式cars*.make等价于cars.collect{ it.make }。当引用的属性不是包含列表的属性时,Groovy 的 GPath 表示法允许使用快捷方式,在这种情况下,它会自动扩展。在前面提到的情况下,cars.make可以使用表达式,但通常建议保留显式点运算符。

(那里的例子谈到了 GPath,但对于列表、地图等也是如此)

lock1.unlock()在这种情况下也是如此lock1*.unlock()。(动态)Groovy 会看到,列表中没有unlock()方法,只是扇出。

至于“所以很可能,lock1 是类锁的对象”,会让你做噩梦。不要猜测 - 找出答案。您可以println(lock1.inspect())了解详细信息,希望该类的作者有远见,添加了一个有用的toString()方法。检查文档,函数返回的内容,您分配locks1的内容。使用工具,告诉你类型(IDE,调试器,...)。

对于开发人员来说,更好的命名有助于:

// BAD naming
def locks1 = smartThings.getAll(Lock, clientId)
// better naming, add the type if it helps you or your IDE
Collection<Lock> allLocks = smartThings.getAll(Lock, clientId)

现在,如果你打电话给allLocks.lock(),事情就更明显了。

为了防止隐式传播运算符,您可以在 groovy 脚本中使用静态编译。例如:

class Lock {
    def lock() { println "lock" }
    def unlock() { println "unlock" }
}

@groovy.transform.CompileStatic
class X {
    public static main() {
        [new Lock()].lock()
    }
}

这不会编译:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
x.groovy: 9: [Static type checking] - Cannot find matching method java.util.List#lock(). Please check if the declared type is correct and if the method exists.
 @ line 9, column 3.
                [new Lock()].lock()
     ^

1 error

使用显式扩展运算符 ( [new Lock()]*.lock()) 进行编译。

于 2019-06-19T07:56:00.507 回答
0

您在这里有 2 个选项:

1) 使用 Groovy 的扩展运算符对列表的每个元素调用该方法:

List lock1 = [.....]
lock1.*lock()

2)使一个Lock类扩展或包含一个元素列表,并为其添加一个类级别的方法:

class Lock {
  List locks

  def lock() {
    locks.*lock()
  }

  // this method allows for calls like lock1[42].lock()
  def getAt( int ix ) { 
    locks[ ix ] 
  } 
}

实际上,继承对于物联网设备是不利的。

于 2019-06-19T00:05:26.717 回答