When식에서는 조건이 엇갈려도 속성이 Mutable이기 때문에 스마트카드를 주지 않습니다!시간의 대응법
Qita→QrunchQiita Edition의 자기 전재를 옮기기 위해서다.
이것은 최근에 코드가 생성한 어둠 속에서 마시는 필터다.
4자리 행 코드를 생성하고 2자리 숫자를 생성했습니다.
따라서 샘플 코드는 자동으로 생성된 악취 코드이므로 양해해 주십시오.
발생한 문제
다음 코드를 썼다고 가정해 보세요.쓰여 있거나.
class XxxBuilderScope {
var duplicatedField: DuplicatedField? = null
fun String.toDuplicatedField() = DuplicatedField.String(this)
fun Int.toDuplicatedField() = DuplicatedField.Int(this)
fun Regex.toDuplicatedField() = DuplicatedField.Regex(this)
operator fun DuplicatedField?.div(value: Int) = DuplicatedField.Int(value)
operator fun DuplicatedField?.div(value: String) = DuplicatedField.String(value)
operator fun DuplicatedField?.div(value: Regex) = DuplicatedField.Regex(value)
sealed class DuplicatedField {
data class String(val value: kotlin.String) : DuplicatedField()
data class Int(val value: kotlin.Int) : DuplicatedField()
data class Regex(val value: kotlin.text.Regex) : DuplicatedField()
}
fun build() {
val builder = Unit
when(duplicatedField) {
is DuplicatedField.String -> println(duplicatedField.value)
is DuplicatedField.Int -> println(duplicatedField.value)
is DuplicatedField.Regex -> println(duplicatedField.value)
}
}
}
이 코드는 컴파일할 수 없습니다.다음 오류가 발생했습니다.Error:(26, 50) Kotlin: Smart cast to 'XxxBuilderScope.DuplicatedField.String' is impossible, because 'duplicatedField' is a mutable property that could have been changed by this time
네.표제 회수.정음 속성은 기본적으로 다른 라인에서 다시 쓸 가능성이 있기 때문에 스마트 방송을 할 수 없다.
대단해!kotlinc는 라인의 안전을 고려하는 똑똑한 컴파일러입니다!
해결책
일반적인 처리 방법은 두 가지가 있다.수동으로 할당할지, val의 로컬 변수를 다시 대입할지.
여기에는 후자의 방법과 코틀린 1.3에 새로 추가된 문법을 사용해 우아하게 풀어낸다.
수정된 코드는 when 부분만 표시됩니다.
when(val v = duplicatedField) {
is DuplicatedField.String -> println(v.value)
is DuplicatedField.Int -> println(v.value)
is DuplicatedField.Regex -> println(v.value)
}
응, 간단하지?(cv: 튀니지 펭귄)덤
샘플 코드를 생성하는 코드의 일부(Kotlinpoet)
또한build ()는 다른 곳에 있습니다
OSS입니다.justincase-jp/AWS-CDK-Kotlin-DSL(홍보)
private fun TypeSpec.Builder.addPropertyForDuplicatedMethods(name: String, methods: List<KFunction<*>>) {
val decapitalName = name.decapitalize()
val capitalName = name.capitalize()
// sealed class DuplicatedField
val sealedType = TypeSpec.classBuilder(capitalName)
.addModifiers(KModifier.SEALED)
// var duplicatedField: DuplicatedField? = null
val sealedClassName = ClassName("", capitalName)
val prop = PropertySpec.builder(decapitalName, sealedClassName.copy(nullable = true))
.initializer("null")
.mutable(true)
.build()
addProperty(prop)
methods.forEach { func ->
val parameterType = func.parameters.single { it.kind == KParameter.Kind.VALUE }.type.classifier as KClass<*>
// data class String(val value: kotlin.String) : DuplicatedField()
val constructor = FunSpec.constructorBuilder()
.addParameter("value", parameterType)
.build()
val clazz = TypeSpec.classBuilder(parameterType.simpleName!!)
.primaryConstructor(constructor)
.addProperty(
PropertySpec.builder("value", parameterType)
.initializer("value")
.build()
).superclass(sealedClassName)
.build()
sealedType.addType(clazz)
// fun String.toDuplicatedField() = DuplicatedField.String(this)
val converterFunc = FunSpec.builder("to$capitalName")
.receiver(parameterType)
.returns(sealedClassName)
.addStatement("return $capitalName.${parameterType.simpleName}(this)")
.build()
addFunction(converterFunc)
// operator fun DuplicatedField?.div(value: Int) = DuplicatedField.Int(value)
val operatorFunc = FunSpec.builder("div")
.receiver(parameterType.asClassName().copy(nullable = true))
.addParameter("value", parameterType)
.returns(sealedClassName)
.addStatement("return $capitalName.${parameterType.simpleName}(value)")
.build()
addFunction(operatorFunc)
}
addType(sealedType.build())
}
Reference
이 문제에 관하여(When식에서는 조건이 엇갈려도 속성이 Mutable이기 때문에 스마트카드를 주지 않습니다!시간의 대응법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/toliner/articles/52c52d8833ebe1a1dfe1텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)