ссылка участника в Kotlin (: :) - PullRequest
3 голосов
/ 20 января 2020
class Student(val id: Int, val name: String)

fun main() {
    val list = arrayListOf<Student>(Student(200, "Lim"), Student(100, "Kim"), Student(300, "Park"))

    println(list.map { Student::name })
    println(list.map { student -> student.name })
}

Результат:

[val Student.name: kotlin.String, val Student.name: kotlin.String, val Student.name: kotlin.String]
[Lim, Kim, Park]

Я не понимаю, почему это происходит.

Ответы [ 2 ]

7 голосов
/ 20 января 2020

Давайте посмотрим, что на самом деле является String::name. Это KProperty1<Student, String>. Этот интерфейс также реализует (Student) -> String. Итак, мы на самом деле имеем дело с лямбдой, которая принимает Student в качестве параметра и возвращает String.

Теперь, что берет функция map? Функция map принимает лямбду, которая отображает один тип на другой ((T) -> R), что означает, что мы можем передать ему Student::name. Как и для любой функции, вы помещаете параметры в скобки.

list.map(Student::name) // variant 1

Если вы хотите определить свою собственную лямбду, вы можете сделать это следующим образом:

val lambda: (Student) -> String = { it.name }
list.map(lambda) // variant 2

Обратите внимание, как лямбда передается в скобках в качестве параметра. Эти скобки могут быть опущены, если вы вставите лямбду (а лямбда - последний параметр этой функции):

list.map { it.name } // variant 3

Давайте посмотрим, что с вами произошло. Вы передали ссылку внутри лямбды:

list.map { Student::name }

, что означает, что вы преобразуете любой элемент в списке в ссылку на свойство name. Итак, вы хотите go с вариантом 1, 2 или 3.

2 голосов
/ 20 января 2020

Как уже говорилось в комментарии, ваша первая операция map отображает ссылку на поле name в class Student, которое затем печатается.
Ваша вторая отображает значение этого поля для каждого экземпляр Student.

Вы можете использовать ссылку на поле, чтобы отобразить значения, но вы должны использовать немного другой синтаксис для него: map(...) вместо map{ ... }, см. эти примеры:

fun main(args: Array<String>) {
    val list = arrayListOf<Student>(Student(200, "Lim"), Student(100, "Kim"), Student(300, "Park"))

    // map and print field reference of the class
    println(list.map { Student::name })

    // map and print field reference for each instance by lambda expression
    println(list.map { student -> student::name })

    // map and print values by field reference for each instance
    println(list.map(Student::name))

    // map and print values by transformation for each instance by lambda expression
    println(list.map { student -> student.name })
}

Поэтому вывод

[val de.os.kotlin.Student.name: kotlin.String, val de.os.kotlin.Student.name: kotlin.String, val de.os.kotlin.Student.name: kotlin.String]
[val de.os.kotlin.Student.name: kotlin.String, val de.os.kotlin.Student.name: kotlin.String, val de.os.kotlin.Student.name: kotlin.String]
[Lim, Kim, Park]
[Lim, Kim, Park]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...