Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Generics 科特林的安全流畅演员?_Generics_Kotlin_Casting_Fluent - Fatal编程技术网

Generics 科特林的安全流畅演员?

Generics 科特林的安全流畅演员?,generics,kotlin,casting,fluent,Generics,Kotlin,Casting,Fluent,具有以下扩展功能: inline fun <reified OUT> Any.cast(): OUT = this as OUT inline fun <reified IN, reified OUT: IN> IN.downcast(): OUT = this as OUT inline fun <reified IN: OUT, reified OUT> IN.upcast(): OUT = this as OUT 这就是我所说的括号地狱。通过语法,我试

具有以下扩展功能:

inline fun <reified OUT> Any.cast(): OUT = this as OUT
inline fun <reified IN, reified OUT: IN> IN.downcast(): OUT = this as OUT
inline fun <reified IN: OUT, reified OUT> IN.upcast(): OUT = this as OUT
这就是我所说的括号地狱。通过语法,我试图实现以下目标(不安全的强制转换版本):

source.cast().someField.cast().someField.cast().someField.cast().desiredField
虽然它不是一个较短的语法,但可读性更高,并且没有括号地狱。问题是,我以这种方式丢失了类型检查,因此我可能会编写
“abc”.cast()
,并导致异常



我如何才能使这更安全,并保持流畅的语法?

您将术语“向上播放”和“向下播放”颠倒过来。向下转换(转换为子类)本质上是不安全的。使用泛型方法可以防止您意外地强制转换到不可能是子类的对象,但是由于您必须检查合格性以确保安全,因此我不认为使用泛型方法是值得的。向上转换(转换为超类)是多余的,所以不需要函数。@Tenfour04。是的,我上下都搞砸了:我加上了向上投射只是为了完整性。
val x1: Number = 42
val x2: String = "abc"
val x3: Double = 3.14

val y1: Int = x1.downcast<Number, Int>()
val y2: CharSequence = x2.upcast<String, CharSequence>()
val y3: Float = x3.cast<Float>() // dangerous, crash
x1.downcast<Number, Int>()
x1.downcast<Int>()
interface A1Able
class B1Impl : A1Able { val desiredField = 42 }
class C1Impl : A1Able

interface A2Able
class B2Impl : A2Able { val someField: A1Able = C1Impl() }
class C2Impl : A2Able { val someField: A1Able = B1Impl() }

interface A3Able
class B3Impl : A3Able { val someField: A2Able = C2Impl() }
class C3Impl : A3Able { val someField: A2Able = B2Impl() }

interface A4Able
class C4Impl : A4Able { val someField: A3Able = B3Impl() }

fun main() {
  val source: A4Able = C4Impl()
  val desiredField = ((((source as C4Impl).someField as B3Impl).someField as C2Impl).someField as B1Impl).desiredField
}
source.cast<C4Impl>().someField.cast<B3Impl>().someField.cast<C2Impl>().someField.cast<B1Impl>().desiredField