Является ли дочерний класс Nothing любого другого класса Kotlin? - PullRequest
0 голосов
/ 19 апреля 2020

Следующий код A взят из примеров архитектуры проекта в https://github.com/android/architecture-samples

Функция getTasks() вернет Result<List<Task>>.

Класс data class Error(val exception: Exception) вернет Result<Nothing>().

Я думаю, что код Error(e) вызовет ошибку, потому что он не может вернуть Result<List<Task>>.

Является ли дочерний класс Nothing любого другого класса в Kotlin?

Код A

class TasksLocalDataSource internal constructor(
    private val tasksDao: TasksDao,
    private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
) : TasksDataSource {
    ...
   override suspend fun getTasks(): Result<List<Task>> {
        return withContext(ioDispatcher) {
            try {
                Success(tasksDao.getTasks())
            } catch (e: Exception) {
                Error(e)                   //I think that it will be cause error
            }
        }
    }
   ...
}


interface TasksDao {
  ...
  @Query("SELECT * FROM Tasks")
  suspend fun getTasks(): List<Task>
   ...
}

sealed class Result<out R> {

    data class Success<out T>(val data: T) : Result<T>()
    data class Error(val exception: Exception) : Result<Nothing>()
    object Loading : Result<Nothing>()

    override fun toString(): String {
        return when (this) {
            is Success<*> -> "Success[data=$data]"
            is Error -> "Error[exception=$exception]"
            Loading -> "Loading"
        }
    }
}

1 Ответ

3 голосов
/ 19 апреля 2020

Под "дочерним" классом я предполагаю, что вы имеете в виду sub type? Если да, то Nothing действительно является подтипом любого другого типа в Kotlin. Его противоположный аналог Any?, который является типом super каждого типа в Kotlin.

Nothing, позволяет работать таким функциям, как TODO(). Реализация этой функции:

public inline fun TODO(): Nothing = throw NotImplementedError()

, указывающая, что TODO() никогда ничего не возвращает , т. Е. Всегда выдает исключение во время выполнения. Это то, что позволяет TODO() быть помещенным в любой контекст. Например:

fun foo(): String = TODO()

компилируется без ошибок, даже если TODO() не возвращает String, потому что компилятор знает, что TODO() никогда не вернет ничего (более конкретно, Nothing является подтипом из String и, следовательно, "возвращает" действительный тип в этом выражении.)

Теперь перейдем к вашему вопросу:

Я думаю, что код Error(e) вызовет ошибку, потому что он не может вернуть Result<List<Task>>.

Мы отметили, что Nothing действительно подтип любого другого типа.

Мы также должны отметить, что определение закрытого Result класса, т. е. Result<out R>, использует дисперсионную аннотацию out. Это означает, что параметр типа T из Result всегда только возвращается из Result и никогда не используется Result, т.е. Result ковариантен в T. Цитирование Kotlin документации:

Общее правило: когда объявлен параметр типа T класса C, это может произойти только в out -позиция в членах C, но взамен C<Base> может смело быть супертипом C<Derived>.

Объединение этого правила со знанием того, что Nothing является подтипом любого другого типа, это позволяет Error(e), который реализует Result<Nothing>, быть допустимым возвращаемым значением Result<List<Task>>, и, следовательно, нет ошибки в указанной вами строке кода.

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