我有这样的界面
interface A{
fun test()
}
我有一个实现A的类B1
class B1: A
{
override fun test()
{
print("B1")
}
}
类似于B1
class C1: A
{
override fun test()
{
print("C1")
}
}
我有一个实现A的类A1
class A1 (var test : Test) : A by test
{
init
{
// Based on condition i need to decide the delegation either B1 or C1
}
}
fun main(){
A1(B1()) // By default am sending the object of B1
}
我的问题是我需要根据某些条件在运行时更改init的委托。 有什么办法可以做到吗?
答案 0 :(得分:1)
您可能有一个A1 : A by expression
语法的表达式。在类构造完成之前,在之前对表达式求值。委托语法不允许切换实现。
您仍可以手动编写代码,或使用任何动态代理库,例如CGLib,ButeBubuddy。 JVM中包含java.land.reflect.Proxy
类,您也可以考虑使用它。但是它具有检查异常https://jonnyzzz.com/blog/2018/11/22/proxy/
最后一种选择是在编译时生成代码。 KotlinPoet可能对此有所帮助。您可以将该任务包含在您的Maven或Gradle构建中。好处是您可以控制委派的工作方式,并且不会在代码运行时浪费时间。 https://github.com/square/kotlinpoet
答案 1 :(得分:0)
老实说,我不认为使用by
委托关键字来做到这一点是不值得的。相反,我只是在private var
内部为A
存储A1
并手动转发呼叫。像这样:
class A1 : A {
private var aDelegate: A
init {
aDelegate = if (condition) B1() else C1()
}
override fun test() {
aDelegate.test()
}
}
也就是说,您可以使用一个选项,尽管我不一定会推荐它。它需要为A
的调用者提供A1
的自定义可变实现,但是保留为可选,以便不必使用它:
class MutableA(var aDelegate: A = EmptyA()) : A {
override fun test() {
aDelegate.test()
}
class EmptyA : A {
override fun test() { }
}
}
class A1(private val mutableA: MutableA = MutableA()) : A by delegate {
init {
mutableA.aDelegate = if (condition) B1() else C1()
}
}
因此,您可以将其初始化,例如:
class A1(flag: Boolean, private val mutableA: MutableA = MutableA()) : A by delegate {
init {
mutableA.aDelegate = if (flag) B1() else C1()
}
}
fun main() {
A1(true).test() // prints "B1"
A1(false).test() // prints "C1"
}