#kotlin
Вопрос:
Вопрос:
- Как я могу конкретизировать
object
типы, если они указаны в качестве общего параметра - Или Как я могу реализовать статические свойства в Kotlin?
Я знаю, что самое близкое, что у нас есть к статическим данным, — это использование object
.
Простой Пример
Наличие интерфейса, который будет реализован только объектами
interface SomeObject {
val someProperty: String
}
object AnObject: SomeObject {
override val someProperty = "someValue"
}
И используя интерфейс в качестве общего ограничения, я хотел бы иметь возможность получать доступ к этим свойствам статически.
class GenericClass<O: SomeObject> {
var someValue: String
get() = O.someProperty // This is not possible
}
GenericClass<AnObject>().someValue
Единственным способом было бы также передать объект в качестве параметра конструктора
class GenericClass<O: SomeObject>(
val obj: O
) {
var someValue: String
get() = obj.someProperty
}
GenericClass(AnObject).someValue
Повторяя вопрос выше
- Есть ли способ овеществить этот объект?
- Или есть ли какой-либо другой способ реализации статических свойств типов?
Комментарии:
1. Я думаю, у вас может быть встроенная фабричная функция, которая создает
GenericClass<O>
объекты… Тот, который создает исключение, еслиobjectInstance
значение равно null. Тебе это нравится?2. Я вижу, что статический let swift не несет бремени JVM, и у меня сложилось впечатление, что это сложно для JVM из-за стирания общего типа, но я могу ошибаться. У меня все равно была бы фабрика для создания универсальных объектов, чтобы иметь больше контроля, но не сидя перед проблемой, я просто еще один id10t за клавиатурой 🙂 (и с проблемой я все еще id10t за клавиатурой, но с проблемой, которую нужно решить впереди) 🙂
3. В комментариях вы сказали: «Объекты, которые будут переданы в нее, будут предоставлены этой библиотекой». В этом случае вы можете пометить интерфейс как закрытый интерфейс. Запечатанный интерфейс гарантирует, что пользователям придется выбирать одну из ваших реализаций, которые все являются объектами, поэтому у них нет конструкторов. В качестве альтернативы вы можете использовать класс перечисления, где у каждого члена класса есть одна из ваших реализаций.
4. В качестве альтернативного способа использования отражения вы можете создать макет конструктора для своего универсального класса в сопутствующем объекте с помощью
inline operator fun <reified T: SomeObject> invoke(): GenericClass<T> = GenericClass(T::class.objectInstance ?: error("unsupported type"))
. Если это закрытый интерфейс, вы знаете, что он безопасен от получения типа без связанного объекта. Если только в качестве типа не указан сам интерфейс SomeObject. Вы можете указать поведение по умолчанию вместо того, чтобы бросать, если хотите.5. @MartinMarconcini Да, я понимаю. Заводской метод с овеществлением и ошибками, по-видимому, является лучшим подходом на данный момент. Спасибо за поддержку товарища id10t 🙂
Ответ №1:
Одним из способов овеществления объекта является использование отражения:
inline fun <reified T> getObject(): T? = T::class.objectInstance
Если вы действительно уверены, что универсальный тип будет объектом
inline fun <reified T> getObject(): T = T::class.objectInstance ?: error("Not an object!")
Это может быть использовано в конструкторе макета для GenericClass
class GenericClass private constructor(private val obj: O) {
var someValue: String
get() = obj.someProperty
companion object {
inline operator fun <reified T: SomeObject> invoke(): GenericClass<T> =
GenericClass(T::class.objectInstance ?: error("unsupported type"))
}
}
И может быть вызван по желанию, используя только общий параметр
GenericClass<AnObject>().someValue