Объясните эту структуру функции Kotlin

Я работаю с этой функцией Kotlin. Я знаю, что у нас есть функция с именем mPasswordView!!.setOnEditorActionListener, которая принимает параметр TextView.OnEditorActionListener, но что это за ней? у нас есть фигурные скобки внутри параметра?

mPasswordView!!.setOnEditorActionListener(TextView.OnEditorActionListener { textView, id, keyEvent ->
    if (id == R.id.login || id == EditorInfo.IME_NULL) {
        attemptLogin()
        return@OnEditorActionListener true
    }
    false
})

person Vlad Skurtolov    schedule 23.04.2017    source источник
comment
Хорошо, моя ошибка. Это не функция...   -  person Vlad Skurtolov    schedule 23.04.2017


Ответы (1)


В вашем примере используется функция SAM-конструктора. Слушатель setOnEditorActionListener принимает OnEditorActionListener в качестве параметра. Этот интерфейс имеет только один метод, который необходимо реализовать, что делает его интерфейсом единого абстрактного метода (SAM).

Полный синтаксис для использования этого метода в Java:

mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        attemptLogin();
        return true;
    }
});

Индивидуальное преобразование в Kotlin даст вам:

mPasswordView.setOnEditorActionListener(object: TextView.OnEditorActionListener{
    override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean {
        attemptLogin()
        return true
    }
})

Kotlin, однако, позволяет вам использовать методы, которые принимают интерфейсы SAM в качестве параметра с более кратким синтаксисом, вместо этого передавая лямбду. Это называется преобразованием SAM:

mPasswordView.setOnEditorActionListener { v, actionId, event ->
    attemptLogin()
    true
}

Преобразования SAM автоматически определяют, какому интерфейсу соответствует эта лямбда, но вы можете указать это явно, используя нечто, называемое конструктором SAM, это то, что находится в вашем примере кода. Конструктор SAM возвращает объект, реализующий заданный интерфейс, и делает переданную ему лямбду реализацией единственного метода.

mPasswordView.setOnEditorActionListener( TextView.OnEditorActionListener { v, actionId, event ->
    attemptLogin()
    true
})

Это избыточно в данной конкретной ситуации, поскольку существует только один метод с именем setOnEditorActionListener. Но если бы было несколько методов с одним и тем же именем, которые принимали разные интерфейсы в качестве параметров, вы могли бы использовать конструктор SAM, чтобы указать, какую перегрузку метода вы хотите вызвать.

Официальные документы о преобразованиях SAM

person zsmb13    schedule 23.04.2017
comment
А для чего нужен @OnEditorActionListener? - person azizbekian; 24.04.2017
comment
Этот синтаксис можно использовать для указания, из какой функции вы возвращаетесь, если у вас есть вложенные функции. См. здесь: kotlinlang.org/docs/reference/returns.html#return -на-метках . Я считаю, что это на самом деле избыточно в этом конкретном случае. - person zsmb13; 24.04.2017