2017-11-18 6 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. ABTool宣言でinner abstractsealedを交換してください。
  2. 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}" 
    } 
    

(あるいは、代わりABToolの範囲に外BoxBBoxA移動し、インナーとしてABをマーキング)ABToolフィールドを追加する

+0

インスタンス化の方法については混乱しています。 'val a = A()'を与えて、私は 'ABTool.AB.BoxA(a)'を試しました。私は 'BoxA'は私が' AB'をインスタンス化したいと思う、おそらく 'BoxA'は内部だから? 'ABTool.AB()。Box​​A(a)'は機能しません。 'ABTool().Ab()。Box​​A(a)'はうまくいきません。なぜなら、ABToolはコンストラクタを必要とするかもしれないからです...しかし、それを構築することは私が最初にやろうとしていることです。これはコンパニオンクラスや何かにある必要があることが分かりませんか? **インスタンス化の仕方を理解できますか?**ありがとうございます。 – sirksel

+1

確かに、それは複雑です。 'ABTool'の一次コンストラクタで' val obj:AB'が必要ですか?ABToolを作成する前に、 'AB'(' BoxA'または 'BoxB')を作成する必要がありますが、' inner'なので、その時点で 'ABTool'インスタンスが存在する必要があります。 – hotkey

+0

外のデータクラスを忘れてしまった場合、私は理解できないもっと簡単な部分があります... 'BoxA'と' BoxB'のコンストラクタは 'AB'の*インスタンス*に依存しています'AB'型のオブジェクトインスタンスは' BoxA'または 'BoxB'(ABは抽象であり、' BoxA'とBoxB'は 'AB'を持つ唯一のクラスであるため)を作成することによってのみ作成できますスーパークラスとして)...インスタンス化することはできますか? (私は内部クラスの私の理解の重要なリンクを欠いていると思っている...) – sirksel

1

が代替となり:

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で未使用であることを起こるので、あなたはそこからそれを削除し、それBoxABoxBval作ることができます。

関連する問題