Я использую Реализация путем делегирования для создания своего рода системы компонентов-сущностей.
Упрощенный пример:
// attribute 1: can take damage
interface Damageable {
val broken: Boolean
fun takeDamage(dmg: Int)
}
// simple implementation
class HpComponent(private var hp: Int): Damageable {
override val broken: Boolean
get() = hp <= 0
override fun takeDamage(dmg: Int) {
hp -= dmg
}
}
// attribute 2: something with electricity
interface Electric {
fun overcharge()
}
// implementation where overcharge damages the component
class PlainElectricComponent(private val component: Damageable): Electric {
override fun overcharge() {
component.takeDamage(10)
}
}
// oven entity
class Oven: Damageable by HpComponent(hp=20), Electric by PlainElectricComponent(this)
Компилятор выдает ошибку при использовании this
в конструкторе PlainElectricComponent
: 'this' is not defined in this context
. Ответы на этот вопрос говорят, что из-за ограничений, связанных с JVM, использование указатель this
невозможен на этом этапе построения объекта.
Я знаю, что могу инициализировать component
позже, например. по
class PlainElectricComponent: Electric {
lateinit var component: Damageable
...
}
class Oven(private val ec: PlainElectricComponent = PlainElectricComponent()):
Damageable by HpComponent(hp=20),
Electric by ec
{
init {
ec.component = this
}
}
но это вызывает уродливое свойство конструктора и требует дополнительной проводки, о которой можно легко забыть.
Знаете ли вы другой способ сохранить объявление компонентов для сущности, которое прямолинейно?
PS: Имея Oven
реализацию интерфейсов, я могу полноценно использовать проверку типов компилятора, интеллектуальное приведение и т.д.