在 Kotlin 中密封 class 之外的引用?
Reference outside the sealed class in Kotlin?
我正在尝试创建一个 class,它使用自己的状态来操作它引用的外部对象的状态。外部对象可以是classA或B,两者类似,但不受作者控制。因此,根据 .
创建了一个密封的 class 来访问它们的共同属性
// *** DOES NOT COMPILE ***
class A { // foreign class whose structure is not modifiable
val prop get()= "some string made the Class-A way"
}
class B { // foreign class whose structure is not modifiable
val prop get()= "some string made the Class-B way"
}
data class ABTool (val obj:AB, val i:Int, val j:Int) {
// class that manipulates i and j and uses them to do
// things with AB's "common" attributes through the sealed class AB
sealed class AB { // substitute for a common interface
abstract val prop: String
abstract val addmagic: String
data class BoxA(val o:A) : AB() {
override val prop get()= o.prop
override val addmagic get() = prop + this@???.magic // HOW TO REFERENCE?
}
data class BoxB(val o:B) : AB() {
override val prop get()= o.prop
override val addmagic get() = this@???.magic + prop // HOW TO REFERENCE?
}
}
val magic get()= "magic: ${i*j}"
}
现在的问题是我发现我不能按照我想要的方式操作外部对象,因为密封的 class 不能引用它的外部 class成员。有没有更好的方法来完成这项工作,即使使用不同的方法(除了密封 class),同时:
- 不改变外国classes A或B;
- 考虑到 A 和 B(以及实际情况中的许多其他)相似,因此我正在尝试编写一个工具来计算 A 和 B,并使用相同的代码库为 A 和 B 添加魔法;
- 注意到虽然 ABTool 工具是相同的,但在 A 和 B 中应用它们来添加魔法的方式略有不同,就像访问 A 和 B 的概念上共同的元素可能不同一样。
对此或类似解决方法有任何想法吗?也许是我还没有想到的更实用的方法?
如果ABTool
被密封class是你可以放弃的东西,那么这里有一个解决方案:
- 在
ABTool
声明处将 sealed
替换为 inner abstract
;
- 同时将
BoxA
和 BoxB
标记为 inner
;
data class ABTool(val obj: AB, val i: Int, val j: Int) {
inner abstract class AB {
abstract val prop: String
abstract val addmagic: String
inner class BoxA(val o: A) : AB() {
override val prop get() = o.prop
override val addmagic get() = prop + magic
}
inner class BoxB(val o: B) : AB() {
override val prop get() = o.prop
override val addmagic get() = magic + prop
}
}
val magic get() = "magic: ${i * j}"
}
(或者,不是将 AB
标记为内部,而是将 BoxA
和 BoxB
移出 ABTool
的范围)
另一种方法是将 ABTool
字段添加到 AB
:
sealed class AB(val tool: ABTool) {
abstract val prop: String
abstract val addmagic: String
data class BoxA(val o:A, tool: ABTool) : AB(tool) {
override val prop get()= o.prop
override val addmagic get() = prop + tool.magic
}
data class BoxB(val o:B, tool: ABTool) : AB(tool) {
override val prop get()= o.prop
override val addmagic get() = tool.magic + prop
}
}
并在从 ABTool
创建时传递 this
。毕竟,这正是 inner
真正做的事情。
在这种特定情况下,该字段恰好在 AB
本身未使用,因此您可以从那里删除它并在 BoxA
和 BoxB
中将其设为 val
.
我正在尝试创建一个 class,它使用自己的状态来操作它引用的外部对象的状态。外部对象可以是classA或B,两者类似,但不受作者控制。因此,根据
// *** DOES NOT COMPILE ***
class A { // foreign class whose structure is not modifiable
val prop get()= "some string made the Class-A way"
}
class B { // foreign class whose structure is not modifiable
val prop get()= "some string made the Class-B way"
}
data class ABTool (val obj:AB, val i:Int, val j:Int) {
// class that manipulates i and j and uses them to do
// things with AB's "common" attributes through the sealed class AB
sealed class AB { // substitute for a common interface
abstract val prop: String
abstract val addmagic: String
data class BoxA(val o:A) : AB() {
override val prop get()= o.prop
override val addmagic get() = prop + this@???.magic // HOW TO REFERENCE?
}
data class BoxB(val o:B) : AB() {
override val prop get()= o.prop
override val addmagic get() = this@???.magic + prop // HOW TO REFERENCE?
}
}
val magic get()= "magic: ${i*j}"
}
现在的问题是我发现我不能按照我想要的方式操作外部对象,因为密封的 class 不能引用它的外部 class成员。有没有更好的方法来完成这项工作,即使使用不同的方法(除了密封 class),同时:
- 不改变外国classes A或B;
- 考虑到 A 和 B(以及实际情况中的许多其他)相似,因此我正在尝试编写一个工具来计算 A 和 B,并使用相同的代码库为 A 和 B 添加魔法;
- 注意到虽然 ABTool 工具是相同的,但在 A 和 B 中应用它们来添加魔法的方式略有不同,就像访问 A 和 B 的概念上共同的元素可能不同一样。
对此或类似解决方法有任何想法吗?也许是我还没有想到的更实用的方法?
如果ABTool
被密封class是你可以放弃的东西,那么这里有一个解决方案:
- 在
ABTool
声明处将sealed
替换为inner abstract
; - 同时将
BoxA
和BoxB
标记为inner
;
data class ABTool(val obj: AB, val i: Int, val j: Int) {
inner abstract class AB {
abstract val prop: String
abstract val addmagic: String
inner class BoxA(val o: A) : AB() {
override val prop get() = o.prop
override val addmagic get() = prop + magic
}
inner class BoxB(val o: B) : AB() {
override val prop get() = o.prop
override val addmagic get() = magic + prop
}
}
val magic get() = "magic: ${i * j}"
}
(或者,不是将 AB
标记为内部,而是将 BoxA
和 BoxB
移出 ABTool
的范围)
另一种方法是将 ABTool
字段添加到 AB
:
sealed class AB(val tool: ABTool) {
abstract val prop: String
abstract val addmagic: String
data class BoxA(val o:A, tool: ABTool) : AB(tool) {
override val prop get()= o.prop
override val addmagic get() = prop + tool.magic
}
data class BoxB(val o:B, tool: ABTool) : AB(tool) {
override val prop get()= o.prop
override val addmagic get() = tool.magic + prop
}
}
并在从 ABTool
创建时传递 this
。毕竟,这正是 inner
真正做的事情。
在这种特定情况下,该字段恰好在 AB
本身未使用,因此您可以从那里删除它并在 BoxA
和 BoxB
中将其设为 val
.