Как классы для устройств и датчиков реализованы в приложениях Samsung SmartThings? - PullRequest
1 голос
/ 19 июня 2019

мы хотим реализовать инфраструктуру для Samsung Groovy SmartThings. Конечно, основная часть инфраструктуры - это реализация различных классов для каждого устройства с соответствующими им методами. Например, для устройств блокировки мы предположили, что у нас есть класс блокировки с методами lock () и unlock (). Проблема здесь в том, что у нас есть эта часть кода в одном из приложений SmartThings, которые находятся в Groovy:

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

Таким образом, наиболее вероятно, что lock1 является объектом для блокировки класса, а lock () и unlock () являются методами для этого класса. Вот эта вещь: Использование команды lock1 [0] .unlock () разблокирует номер замка двери № 0, но использование команды lock1.unlock () разблокирует все замки двери.

Вопрос здесь в том, как создается класс? Если lock1 - это список объектов, как мы можем использовать команду, подобную lock1.unlock ().

Дело в том, что оба объекта должны иметь одинаковое имя lock1, а оба метода - один и тот же метод с именем lock ().

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 19 июня 2019

Здесь возникает проблема (неявная) оператор распространения в Groovy.

Выражение cars*.make эквивалентно cars.collect{ it.make }.Нотация GPath Groovy позволяет использовать ярлык, когда указанное свойство не является свойством содержащего списка, в этом случае оно автоматически распространяется.В ранее упомянутом случае можно использовать выражение 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()) компилируется.

0 голосов
/ 19 июня 2019

У вас есть 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 ] 
  } 
}

На самом деле наследование ПЛОХО для устройств IoT.

...