Kotlin - Попытка факторизовать код с помощью функции высокого порядка - PullRequest
0 голосов
/ 01 апреля 2020

Я довольно новичок в Kotlin, и я хотел бы посмотреть, может ли использование функций высокого порядка помочь в моем случае.

Мой вариант использования заключается в том, что мне нужно вызывать методы производный класс IInterface для отправки событий одному или нескольким компонентам. И я хотел бы сделать этот шаблон c, и я хочу проверить, может ли функция высокого порядка помочь. Пример кода поможет понять (ну, я на это надеюсь!).

private val eventListeners = mutableListOf<IEventInterface>() // List filled somewhere else!

private fun sendConnectionEvent(dummyString: String) {
    val deadListeners = mutableListOf<IEventInterface>()

    eventListeners.forEach {
        try {
            it.onConnectionEvent(dummyString)
        } catch (e: DeadObjectException) {
            Log.d(TAG, "Removing listener - Exception ${e.message}")
            deadListeners.add(it)
        }
    }

    deadListeners.forEach { it ->
        eventListeners.remove(it)
    }
}

private fun sendWonderfulEvent(dummyString: String, dummyInt: Int) {
    val deadListeners = mutableListOf<IEventInterface>()

    eventListeners.forEach {
        try {
            it.onWonderfulEvent(dummyString, dummyInt)
        } catch (e: DeadObjectException) {
            Log.d(TAG, "Removing listener - Exception ${e.message}")
            deadListeners.add(it)
        }
    }

    deadListeners.forEach { it ->
        eventListeners.remove(it)
    }
}

Я добавил 2 аналогичных метода (у меня будет еще много в реальном случае) и я думаю (надеюсь! ) что-то можно сделать, но я не могу заставить работать функцию высокого порядка в этом случае, потому что:

  • Я хочу вызвать один и тот же метод в нескольких экземплярах. , а не «просто» базовая c функция
  • Что еще хуже, методы, которые мне нужно вызвать, не имеют такого же прототипа (это было бы слишком просто!).

Надеюсь, это достаточно ясно.

Спасибо за вашу помощь!

VR

Ответы [ 2 ]

1 голос
/ 01 апреля 2020

Вот как это можно сделать

fun onEvent(body: (IEventInterface) -> Unit) {
    val deadListeners = mutableListOf<IEventInterface>()
    eventListeners.forEach {
        try {
            body(it)
        } catch (ex: DeadObjectException) {
            Log.d(TAG, "Removing listener - Exception ${e.message}")
            deadListeners.add(it)
        }
    }

    deadListeners.forEach { it ->
        eventListeners.remove(it)
    }
}
0 голосов
/ 01 апреля 2020
  • Предположим, что интерфейс подобен этому:

    interface IEventInterface {
        fun onConnectionEvent(dummyString: String)
        fun onWonderfulEvent(dummyString: String, dummyInt: Int)
    }
    
  • Определите универсальный тип c, который реализует определенный вами интерфейс (<T : IEventInterface>)

  • Определите изменяемый список этого типа для получения вашей реализации (MutableList<T>.removeIfThrows)
  • Ожидайте функцию расширения для вашего типа, которая выполнит заданную вами проверку c (и пользовательские параметры, если вы хотите)
  • Используя apply и возвращая экземпляр, вы можете запустить свой код как конвейер
  • Выполнить пользовательскую проверку, когда хотите

    private fun <T : IEventInterface> MutableList<T>.removeIfThrows(validation: T.() -> Unit, customLogMessage: String? = null): MutableList<T> {
        return apply {
            removeIf {
                it.runCatching {
                    validation()
                }.onFailure { error ->
                    print(customLogMessage ?: "Removing listener - Exception ${error.message}")
                }.isFailure
            }
        }
    }
    
  • Определите заданную вами реализацию c, передав в качестве параметра только функцию с пользовательской проверкой

    private fun <T : IEventInterface> MutableList<T>.sendConnectionEvent(dummyString: String) = removeIfThrows({
        onConnectionEvent(dummyString)
    })
    
    private fun <T : IEventInterface> MutableList<T>.sendWonderfulEvent(dummyString: String, dummyInt: Int) = removeIfThrows({
        onWonderfulEvent(dummyString, dummyInt)
    })
    
  • Теперь вы можете запускать свой код как конвейер, модифицирующий исходный объект, например это

    private fun nowYouCanDoSomethingLikeThis() {
        eventListeners
                .sendConnectionEvent("some dummy string")
                .sendWonderfulEvent("some another dummy string", 123)
    }
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...