Наследование реализаций интерфейсов на Kotlin
Мне нужно реализовать два интерфейса. У каждого интерфейса будет по несколько наследников. А потом нужно создать интерфейс, который будет состоять из наследников предыдущих интерфейсов, причем неважно каких. Сразу на примере - есть интерфейсы кузов машины и двигатель, у каждого есть по значению:
// кузов
interface Carcase {
val aerodynamics: Float
fun getAD(){return aerodynamics}
}
// двигатель
interface Engine {
val power: Int
fun getP(){return power}
}
У каждого есть по несколько реализаций:
class Lada: Carcase {
override val aerodynamics: Float = 1.0f
}
class Volvo: Carcase {
override val aerodynamics: Float = 1.5f
}
class V1: Engine {
override val power: Int = 10
}
class V3: Engine {
override val power: Int = 20
}
class V5: Engine {
override val power: Int = 30
}
А теперь мне надо реализовать интерфейс или класс, который будет собирать из двух реализаций одну, что то вроде этого:
// правильно ли это и вообще возможно ли - не знаю
interface Car<S,T>: Carcase, Engine {
fun getSpeed{
return( S.getAD() * T.getP() ) //?????
}
}
В итоге я должен писать в основном коде что то вроде:
val car1 = Car<Lada, V1>
val car2 = Car<Volvo, V5>
И должно работать:
val s1 = car1.getSpeed() // 1.0f * 10
val s2 = car2.getSpeed() // 1.5f * 30
Вопрос: как правильно реализовать такое наследование? Помогут и прямой ответ ответ на вопрос, и ссылки на книги (с указанием раздела, что смотреть). Так как я сам даже не понимаю, в какую сторону тут надо гуглить.
Ответы (1 шт):
Могу предложить что-то подобное (композиция вместо наследования).
class Car<C, E>(private val case : C, private val engine: E) where C:Carcase, E:Engine {
fun getSpeed() : Float {
return( case.getAD() * engine.getP() )
}
}
Использование
val car1 = Car(Lada(), V1())
val car2 = Car(Volvo(), V5())
println("Lada: ${car1.getSpeed()}") // Lada: 10.0
println("Volvo: ${car2.getSpeed()}") // Volvo: 45.0
Бонус. Можно использовать inline reified функцию для быстрого "производства" машин.
inline fun <reified C: Carcase, reified E: Engine> produce(): Car<C, E> {
val case = C::class.constructors.first().call()
val engine = E::class.constructors.first().call()
return Car(case, engine)
}
Использование
val car1 = produce<Lada, V1>()
val car2 = produce<Volvo, V5>()
Функция написана с условием, что у классов корпуса и двигателя есть только один конструктор без параметров!