2017-11-18 198 views
2

我试图创建一个类,它使用自己的状态来操作它所持有的引用的外部对象的状态。外部对象可以是A类或B类,它们是相似的,但不受作者控制。因此,每个this earlier answer from @SimY4创建一个密封的类以访问其共同属性。Kotlin密封课程之外的参考?

// *** 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 + [email protected]???.magic // HOW TO REFERENCE? 
    } 
    data class BoxB(val o:B) : AB() { 
     override val prop get()= o.prop 
     override val addmagic get() = [email protected]???.magic + prop // HOW TO REFERENCE? 
    } 
    } 
    val magic get()= "magic: ${i*j}" 
} 

现在的问题是,我已经想通了,我不能在我希望的方式与外部对象进行操作,因为密封类不能引用其外部类的成员。有没有更好的方法来完成这项工作,即使使用不同的方法(密封类别除外):

  • 不改变外国类别A或B;
  • 尊重A和B(和真实案例中的许多其他人)是相似的,所以我正在尝试编写一个工具,它可以用相同的代码库计算并向A和B添加魔法;和
  • 注意虽然ABTool工具是相同的,但它们应用于添加魔法的方式在A和B之间略有不同,就像访问概念上的A和B的常见元素可能会不同。

对这个或类似的解决方法有什么想法?也许我还没有设想一个更实用的方法呢?

回答

2

如果ABTool是一个密封类的东西,你可以放弃,那么这里有一个解决方案:

  1. 更换sealedinner abstractABTool声明;
  2. Mark BoxA and BoxB as 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作为内,移动BoxABoxB出它到的ABTool范围)

+0

我很困惑如何实例化。给定'val a = A()',我试过'ABTool.AB.BoxA(a)'。我认为'BoxA'要我实例化'AB',也许是因为'BoxA'是内在的? 'ABTool.AB()。Box​​A(a)'不起作用,也许是因为'AB'是抽象的? ABTool()。AB().BackA(a)'不起作用,也许是因为ABTool需要构造函数?......但构造它就是我想要做的。我是否错过这需要在伴侣课堂或其他? **你能帮我理解如何实例化吗?**谢谢。 – sirksel

+1

事实上,这很复杂。 'ABTool'的主构造函数中是否需要'val obj:AB'?当它在那里时,你需要在创建'ABTool'之前创建'AB'('BoxA'或'BoxB'),但由于它们是'inner',所以它们需要一个'ABTool'实例。 – hotkey

+0

暂时忘记外部数据类,下面是一个更简单的部分,我无法掌握......如果'BoxA'和'BoxB'的构造函数(因为它们是'inner'')依赖于AB的*实例*被看见,并且一个'AB'类型的对象实例只能通过创建一个'BoxA'或'BoxB'来创建(因为'AB'是抽象的,'BoxA'和'BoxB'是唯一具有'AB'的类。作为一个超类)......他们可以实例化吗? (我一直认为我错过了理解内部类的关键环节......) – sirksel

1

另一种方法是添加一个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本身未使用的,所以你可以从那里删除它,让它在valBoxABoxB