Можно ли указать статическую функцию в интерфейсе Kotlin?
Я хочу сделать что-то вроде этого:
interface Serializable<FromType, ToType> {
fun serialize(): ToType
companion object {
abstract fun deserialize(serialized: ToType): FromType
}
}
или даже это будет работать для меня:
interface Serializable<ToType> {
fun serialize(): ToType
constructor(serialized: ToType)
}
но ни один не компилируется. Есть ли синтаксис для этого, или я буду вынужден использовать сделать это интерфейс для фабрики? Или есть другой ответ? Это было бы здорово!
3 ответа
В принципе, ничего в companion object
может быть abstract
или же open
(и таким образом быть переопределенным), и нет никакого способа требовать реализации ' companion object
s иметь метод или определять / требовать конструктор в интерфейсе.
Возможное решение для вас - разделить эти две функции на два интерфейса:
interface Serializable<ToType> {
fun serialize(): ToType
}
interface Deserializer<FromType, ToType> {
fun deserialize(serialized: ToType): FromType
}
Таким образом, вы сможете реализовать первый интерфейс в классе и сделать его companion object
реализовать другой:
class C: Serializable<String> {
override fun serialize(): String = "..."
companion object : Deserializer<C, String> {
override fun deserialize(serialized: String): C = C()
}
}
Кроме того, существует серьезное ограничение, заключающееся в том, что в качестве супертипа может использоваться только одна общая специализация типа, поэтому такая модель сериализации через реализацию интерфейса может оказаться недостаточно масштабируемой, что не позволяет использовать несколько реализаций с разными ToType
s.
Для будущего использования также можно передать дочерний класс функции в качестве параметра получателя:
val encodableClass = EncodableClass("Some Value")
//The encode function is accessed like a member function on an instance
val stringRepresentation = encodableClass.encode()
//The decode function is accessed statically
val decodedClass = EncodableClass.decode(stringRepresentation)
interface Encodable<T> {
fun T.encode(): String
fun decode(stringRepresentation: String): T
}
class EncodableClass(private val someValue: String) {
// This is the remaining awkwardness,
// you have to give the containing class as a Type Parameter
// to its own Companion Object
companion object : Encodable<EncodableClass> {
override fun EncodableClass.encode(): String {
//You can access (private) fields here
return "This is a string representation of the class with value: $someValue"
}
override fun decode(stringRepresentation: String): EncodableClass {
return EncodableClass(stringRepresentation)
}
}
}
//You also have to import the encode function separately:
// import codingProtocol.EncodableClass.Companion.encode
Для меня это более оптимальный вариант использования. Вместо одной функции в объекте-экземпляре и другой в объекте-компаньоне, как в вашем примере, мы перемещаем обе функции в объект-компаньон и расширяем экземпляр.
Я относительно новичок в Kotlin. Вот мои 2¢
сопутствующий объект является экземпляром класса и как таковой не может быть унаследован от. Вот почему абстрактной функции не будет места для реализации. В Java для аналогичного результата требуется анонимный класс, реализующий абстрактный класс, но он сильно отличается от переопределяющего метода для экземпляра класса.
Интерфейс нельзя использовать для создания экземпляра, поэтому в интерфейсе нет использования конструктора.
Почему бы вам не создать общий абстрактный класс? Тогда абстрактная или открытая функция будет работать для функций serialize(): ToType и deserialize(serialized: ToType): FromType.