Как сделать так, чтобы в массиве были методы типа объекта? - PullRequest
0 голосов
/ 05 сентября 2018

Этот вопрос состоит в том, чтобы выяснить, возможно ли что-то с языком или нет, а не о конкретной проблеме или случае.

Я все еще изучаю динамичность и функциональные аспекты Kotlin.


Есть ли способ повернуть это:

for (item in myList) item.someMethod()

в нечто вроде:

myList.all().someMethod()

Ответы [ 2 ]

0 голосов
/ 06 сентября 2018

Просто будь проще.

myList.forEach { it.someMethod() }
// or
myList.forEach(Item::someMethod)

Функция расширения также возможна, но, возможно, это уже слишком (по крайней мере, сузьте ее до вашего типа):

fun List<Item>.someMethod() = forEach { it.someMethod() }

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

class MyObj {
  val funnyItems = mutableListOf<Item>()
  val usefulItems = mutableListOf<Item>()
  val whateverItems = mutableListOf<Item>()

  fun List<Item>.someMethod() = forEach { it.someMethod() }
}

он будет вызываться только при наличии соответствующего приемника на месте. Поэтому добавление функции внутри класса MyObj следующим образом работает:

fun callingSomeMethod() = funnyItems.someMethod() // no problem

, но не будет работать за пределами MyObj. Например. рассмотрим main -метод, не входящий в MyObj:

fun main(args: Array<String>) {
  listOf(MyObj())
    .forEach {
    // the following will not work... it is not accessible without appropriate receiver
    // it.funnyItems.someMethod() // doesn't compile...
      with(it) {
        // 'this' is now MyObj which is the required receiver in addition to List<Item>, so the following works:
        this.funnyItems.someMethod()
      }
    }
}
0 голосов
/ 05 сентября 2018

Дано:

data class MyObj(val v: String) {
    fun someMethod() {
        println(v)
    }
}

val myList = listOf(MyObj("A"), MyObj("B"), MyObj("C"))

for (item in myList) item.someMethod()

Вы можете сделать что-то вроде этого:

fun List<MyObj>.someMethod() {
    for (e in this) {
        e.someMethod()
    }
}

fun List<MyObj>.all() = this

Это простая функция расширения в списке определенного типа.

Если вам нужно что-то вроде динамической отправки, подумал, что это было бы невозможно.

Но, возможно, вам нужен шаблон проектирования Composite, в котором и контейнер, и элементы реализуют один и тот же интерфейс. Примерно так:

interface SomeInterface {
    fun someMethod()
}

class MyList(val elements: List<MyObj>) : SomeInterface {
    override fun someMethod() {
        for (e in elements) {
            e.someMethod()
        }
    }
}

data class MyObj(val v: String) : SomeInterface{
    override fun someMethod() {
        println(v)
    }
}

Будет работать аналогично:

val myList = MyList(listOf(MyObj("A"), MyObj("B"), MyObj("C")))

myList.someMethod()

Этот шаблон обеспечивает хороший контракт между коллекцией элементов и одним элементом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...