2011-11-24 3 views
3

반환 유형이 다른 메소드를 오버로드 할 수 없다는 것을 알고 있습니다.오버로드 제한 (여러 유형의 특성 구현)에 대한 작업

trait MultiReader { 
    implicit object RB extends Reader[B] { ... } 
    implicit object RC extends Reader[C] { ... } 

    doSomethingB() 
    doSomethingC() 
} 
: 똑똑하고 내 말은 효율적으로

trait Reader[A] { def read(in: java.io.DataInput): A } 

trait B; trait C 

def doSomethingB()(implicit r: Reader[B]) =() 
def doSomethingC()(implicit r: Reader[C]) =() 

trait MultiReader extends Reader[B] with Reader[C] { // not possible 
    implicit me = this 

    doSomethingB() 
    doSomethingC() 
} 

, 나는이 같은 혼란과 불필요한 내부 클래스 세대를 피하기 위해 싶습니다 그러나 나는 어떤 스마트 전략이 상황에 효율적으로 대처하기 위해이 있는지 궁금합니다

편집

부분적인 해결책입니다. 나는 영감을 얻은 마지막 날에 Miles Sabin이 this gist을 다시 읽었습니다.

type Tagged[U] = { type Tag = U } 
type @@[T, U] = T with Tagged[U] 

trait Reader[A] { def read(in: java.io.DataInput @@ A): A } 

를 그리고이 작품 : 그래서 다음과 같은 작업을 수행 할 수

trait MultiReader { 
    def read(in: java.io.DataInput @@ B): B 
    def read(in: java.io.DataInput @@ C): C 
} 

을하지만 상속이 다소 여전히 분류됩니다

trait MultiReader extends Reader[B] with Reader[C] 

을 ("self-type MultiReader does not conform to Reader[B]'s selftype Reader[B]" 실패).

답변

1

이 여전히 Function1 플러스 필요한 각 유형의 매개 변수에 대한 익명 Reader 인스턴스화하지만 적어도 구문이 더 간결 :

object Reader { 
    implicit def fromFun[A](implicit fun: java.io.DataInput => A): Reader[A] = 
    new Reader[A] { def read(in: java.io.DataInput): A = fun(in) } 
} 
trait Reader[A] { def read(in: java.io.DataInput): A } 

def doSomethingB()(implicit r: Reader[B]): Unit = println(r.read(null)) 
def doSomethingC()(implicit r: Reader[C]): Unit = println(r.read(null)) 

trait MultiReader { 
    implicit def readB(in: java.io.DataInput): B = new B { override def toString = "B" } 
    implicit def readC(in: java.io.DataInput): C = new C { override def toString = "C" } 

    doSomethingB() 
    doSomethingC() 
} 

new MultiReader {} // --> B, C 
0

주요 문제는 유형 매개 변수가 다른 경우에도 스칼라가 제네릭 특성을 두 번 이상 구현할 수 없다는 것입니다.

def doSomethingB()(implicit r: { def read(in: java.io.DataInput @@ B): B }) =() 
def doSomethingC()(implicit r: { def read(in: java.io.DataInput @@ C): C }) =() 

여기 디스패치 버그가있어, 다음 태그 버전으로 호출하면 제대로 작동하지만 흥미롭게도,이 같은 구조 유형을 사용하는 경우, 그것은 실패 (입력이 B 또는 C 태그와 나는 일부러 read를 호출 할 수 있습니다) 둘 다 독서 C으로 전화 할 것이다. 이 작품

sealed trait B; trait C extends B 

trait UpDownReader[Up, Down] { 
    def read[A >: Down <: Up : Manifest](in: java.io.DataInput): A 
} 

class MultiReader(implicit mfx: Manifest[X], mfy: Manifest[Y]) 
    extends UpDownReader[X, Y] { 

    def read[A >: Y <: X](in: java.io.DataInput)(implicit mf: Manifest[A]): A = 
    (if (mf == mfx) new X {} else new Y {}).asInstanceOf[A] 
} 

: BC하나의 클래스 계층 구조 내에 있는지 제약이있는 경우


, 아이디어가 경계 사용하는 것입니다 그러나

val m = new MultiReader 
m.read[B](null) 
m.read[C](null) 

을, 매니 페스트와 '추악한 캐스트'의 '역동적 인'비교가 주어지면 나는 이것을 우아하고 효율적이라고 보지 않을 것입니다. A.