密封课程:
sealed class Alphabet(val name: String) {
object A : Alphabet("A")
object B : Alphabet("B")
object C : Alphabet("C")
object D : Alphabet("D")
object E : Alphabet("E")
companion object {
val array = arrayOf(A, B, C, D, E)
val list = listOf(A, B, C, D, E)
}
override fun toString(): String {
return name
}
}
Run Code Online (Sandbox Code Playgroud)
还有另一个带有伴侣对象的类:
class AlphabetMap {
companion object {
val map = mapOf(
Alphabet.A to 1,
Alphabet.B to 2,
Alphabet.C to 3,
Alphabet.D to 4,
Alphabet.E to 5
)
}
}
Run Code Online (Sandbox Code Playgroud)
如果我想打印数组(或列表):
class AlphabetTest {
@Test
fun printValues() {
Alphabet.array.forEach { print("$it ") };println()
Alphabet.list.forEach { print("$it ") };println()
}
}
Run Code Online (Sandbox Code Playgroud)
它正确打印结果:
A B C D E
A B C D E
Run Code Online (Sandbox Code Playgroud)
但如果我AlphabetMap
在代码中初始化:
class AlphabetTest {
val m = AlphabetMap()
@Test
fun printValues() {
Alphabet.array.forEach { print("$it ") };println()
Alphabet.list.forEach { print("$it ") };println()
}
}
Run Code Online (Sandbox Code Playgroud)
结果神秘地变成了:
null B C D E
null B C D E
Run Code Online (Sandbox Code Playgroud)
第一个元素(A)变为空
如果我定义
val m = AlphabetMap
Run Code Online (Sandbox Code Playgroud)
结果是一样的.
如果我在函数中初始化AlphabetMap:
@Test
fun printValues() {
val m = AlphabetMap() // or val m = AlphabetMap
Alphabet.array.forEach { print("$it ") };println()
Alphabet.list.forEach { print("$it ") };println()
}
Run Code Online (Sandbox Code Playgroud)
结果是一样的 :
null B C D E
null B C D E
Run Code Online (Sandbox Code Playgroud)
但如果我这样做:
@Test
fun printValues() {
Alphabet.array.forEach { print("$it ") };println()
val m = AlphabetMap() // or val m = AlphabetMap
Alphabet.list.forEach { print("$it ") };println()
}
Run Code Online (Sandbox Code Playgroud)
现在一切正常:
A B C D E
A B C D E
Run Code Online (Sandbox Code Playgroud)
如果我将AlphabetMap重写为
class AlphabetMap {
companion object {
val map = mapOf(
//Alphabet.A to 1,
Alphabet.B to 2,
Alphabet.C to 3,
Alphabet.D to 4,
Alphabet.E to 5
)
}
}
Run Code Online (Sandbox Code Playgroud)
结果变成了
A null C D E
A null C D E
Run Code Online (Sandbox Code Playgroud)
如果AlphebetMap是:
class AlphabetMap {
companion object {
val map = mapOf(
Alphabet.E to 5
)
}
}
Run Code Online (Sandbox Code Playgroud)
结果变成:
A B C D null
A B C D null
Run Code Online (Sandbox Code Playgroud)
怎么可能出错?这是一个错误吗?或语言功能?
环境:jdk1.8.0_144,OS X.
<kotlin.version>1.2.0</kotlin.version>
<kotlin.compiler.jvmTarget>1.8</kotlin.compiler.jvmTarget>
<kotlin.compiler.incremental>false</kotlin.compiler.incremental>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-coroutines-core</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test-junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test</artifactId>
<scope>test</scope>
</dependency>
Run Code Online (Sandbox Code Playgroud)
sma*_*ufo 10
另一个解决方案是定义array
/ list
by lazy
,这似乎解决了这里的所有问题。
sealed class Alphabet(val name: String) {
object A : Alphabet("A")
object B : Alphabet("B")
object C : Alphabet("C")
object D : Alphabet("D")
object E : Alphabet("E")
companion object {
val array: Array<Alphabet> by lazy {
arrayOf(A, B, C, D, E)
}
val list: List<Alphabet> by lazy {
listOf(A , B , C , D , E)
}
}
override fun toString(): String {
return name
}
}
Run Code Online (Sandbox Code Playgroud)
现在效果很好。
A B C D E
A B C D E
Run Code Online (Sandbox Code Playgroud)
解决这个问题的唯一方法是将映射定义移到类之外:
val map = mapOf(
Alphabet.A to 1,
Alphabet.B to 2,
Alphabet.C to 3,
Alphabet.D to 4,
Alphabet.E to 5
)
class AlphabetMap {
companion object {
}
}
Run Code Online (Sandbox Code Playgroud)
根据 JetBrain在 youtrack和reddit上的回复,这是按设计的,没有办法解决。
初始化中的循环问题没有通用的解决方案。无论我们提出哪种具体规则,如果对象 A 的初始化程序访问对象 B 并且对象 B 的初始化程序访问对象 A,则其中一个将能够以未初始化状态观察另一个。
归档时间: |
|
查看次数: |
326 次 |
最近记录: |