#android #kotlin
#Android #kotlin
Вопрос:
У меня есть следующий код на языке программирования Dart
class HttpResponse {
final int code;
final String? error;
HttpResponse.ok() : code = 200; <== This functionality
HttpResponse.notFound() <== This functionality
: code = 404,
error = 'Not found';
String toString() {
if (code == 200) return 'OK';
return 'ERROR $code ${error.toUpperCase()}';
}
}
Как я могу добиться этого в Kotlin, я знаю, что могу использовать статические методы, однако статические методы не предназначены для инициализации класса, есть ли способ, которым это может быть достигнуто в Kotlin?
Комментарии:
1. У Kotlin (и Java) нет именованных конструкторов. Вероятно, вы ищете статические фабричные методы.
2. Возможно, вы ищете сопутствующие объекты — они предоставят вам статические функции и будут выглядеть как ваш пример.
3. Самый простой перевод 1: 1 для вашего кода — это, вероятно, сопутствующие объекты. Для вашего конкретного примера класс enum сделает это просто отлично.
Ответ №1:
Вы ищете закрытые классы.
sealed class HttpResponse(val code: Int, val error: String? = null) {
class Ok(code: Int) : HttpResponse(code)
class NotFound(code: Int, error: String?) : HttpResponse(code, error)
override fun toString(): String {
return if (code == 200) "OK"
else "ERROR $code ${error?.toUpperCase()}"
}
}
fun main() {
val okResponse = HttpResponse.Ok(200)
val notFoundResponse = HttpResponse.NotFound(404, "Not found")
}
Комментарии:
1. Могу ли я запретить инициализацию из
HttpResponse
класса, чтобы поддерживать ту же функциональность, что и исходный код из Dart?2. По умолчанию нельзя создавать экземпляры закрытых классов. Попытка создания
HttpResponse(100, "Test")
выдает ошибку.3. Но это позволяет что-то вроде
HttpResponse.Ok(404)
илиHttpResponse.NotFound(200, "ok")
чего нет в коде Dart.4. Я не знаю Dart: ( вы хотите просто вызвать
Ok(200)
безHttpResponse
префикса? Затем просто переместитеclass Ok
внешнюю часть телаHttpResponse
, просто поместите их в один и тот же файл, но без их вложения.
Ответ №2:
Запечатанные классы — это путь:
import java.util.Locale.US
sealed class HttpResponse(val code: Int, val error: String?) {
object Ok : HttpResponse(200, null)
object NotFound : HttpResponse(404, "Not found")
override fun toString() = when (this) {
Ok -> "OK"
NotFound -> "ERROR $code ${error?.uppercase(US)}"
}
}
fun main() {
println(HttpResponse.Ok) // OK
println(HttpResponse.NotFound) // ERROR 404 NOT FOUND
}
Поскольку я не могу предложить редактирование или опубликовать комментарий, я добавляю сюда свою модифицированную версию ответа zOqvxf.
Если вы сохраняете параметры своего суперкласса неэкспонированными таким образом, нет необходимости беспокоиться об использовании HttpResponse.Ok(404)
, как указано в комментарии.
Ответ №3:
Я согласен, что sealed class
это предпочтительный способ, но есть другой вариант сделать конструктор закрытым и получить к нему доступ с помощью заводских методов companion object
. Таким образом, вы можете получить «именованные конструкторы».
data class HttpResponse private constructor(
private val code: Int,
private val error: String? = null,
) {
companion object {
fun ok() = HttpResponse(200)
fun notFound() = HttpResponse(404, "Not found")
}
}
fun main() {
val responseOk = HttpResponse.ok()
val responseNotFound = HttpResponse.notFound()
}