2017-11-18 1 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. BoxABoxBinner으로 표시한다.

    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'를 인스턴스화하기를 원한다고 생각한다. 'ABTool.AB(). BoxA (a)'가 작동하지 않습니다. 'ABTool(). AB(). BoxA (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 할 수 있습니다.

관련 문제