2013-04-19 3 views
5

나는이 작은 물건을 얻지 못한다. 다른 유형의 여러 하위 클래스가있는 추상 클래스 Box 이 있습니다. 예를추출기를 다형성 적용 취소에서 사용하는 방법은 무엇입니까?

abstract class Box 
class StringBox(val sValue : String) extends Box 

를 들어 상자의 동반자 객체의 적용 방법은 간단하다 :

object Box{ 
    def apply(s: String) = new StringBox(s) 
    def apply(b: Boolean) = new BooleanBox(b) 
    def apply(d: Double) = new DoubleBox(d) 
} 

그래서 난

val sb = Box("StringBox) 

좋아이 적용 취소 작성하는 몇 가지 문제를 만들어 쓸 수 있습니다. 나의 첫 생각이이 같은 유형에 패턴 매칭을 사용하는 것이 었습니다 :

def unapply(b: Box) = b match { 
    case sb: StringBox => Some(sb.sValue) 
    case bb: BooleanBox => Some(bb.bValue) 
    case db: DoubleBox => Some(db.dValue) 
    case _ => None 

}

때문에 단순히 타입의 소거 작동하지 않는다.

두 번째 시도는 유형 T 인 일반 Box [T]이고 각 하위 클래스에 을 다시 정의한 추상 유형 멤버였습니다. 예를 들어 :

def unapply[T](b: Box[T]) = b match { 
    case sb: Box[String] => Some(sb.value) 
    case bb: Box[Boolean] => Some(bb.value) 
    case db: Box[Double] => Some(db.value) 
    case _ => None 

불행하게도,이 중 하나가 작동하지 않습니다

abstract class Box[T] {def value : T} 
class StringBox(val sValue : String) extends Box[String] { 
    override def value : String = sValue 
} 

따라서, 나는 나의 적용 취소를 쓰기 다시 할 수 있습니다. 그래서 Box [String]의 명시적인 타입 참조 이 지워지므로 대신 타입 매니페스트를 사용해야합니다. 같은 아마 뭔가 : 여전히

def unapply[T](b: Box[_])(implicit target: Manifest[T]): Option[T] = { 

    if(b.value == target) Some(b.value.asInstanceOf[T]) 
    else None 
} 

이 코드 컴파일 (2.10)하지만하지 않습니다 원하는 암시 적 변환. 왜?

간단한 질문이지만 리플렉션 또는 매니페스트를 사용하지 않고 값 추출을 수행 할 수있는 방법이 있습니까?

다형성과 패턴 일치를 결합하는 간단한 (r) 방법이 있다면 정말 어떤 질문이 있습니까? 그렇지 않다면 스칼라에서 에 다른 방법으로 비슷한 효과가 있습니까?

의견이나 제안이 있으십니까?

대단히 감사합니다.

답변

5

Prolly이 시도 할 수 있습니다 .. :)

abstract class Box[T](val v: T) 

    object Box { 
    def apply(s: String) = new StringBox(s) 
    def apply(b: Boolean) = new BooleanBox(b) 
    def apply(d: Double) = new DoubleBox(d) 

    } 

    class StringBox(sValue: String) extends Box(sValue) 
    object StringBox { 
    def unapply(b: StringBox) = Some(b.v) 
    } 

    class BooleanBox(sValue: Boolean) extends Box(sValue) 
    object BooleanBox { 
    def unapply(b: BooleanBox) = Some(b.v) 
    } 

    class DoubleBox(sValue: Double) extends Box(sValue) 
    object DoubleBox { 
    def unapply(b: DoubleBox) = Some(b.v) 
    } 

을 당신은로 사용할 수 있습니다 -

def useCase[T](box: Box[T]) = box match { 
    case StringBox("StringBoxxx") => "I found the StringBox!" 
    case StringBox(s) => "Some other StringBox" 
    case BooleanBox(b) => { 
      if (b) "Omg! its true BooleanBox !" 
      else "its false BooleanBox :(" 
      } 
    case DoubleBox(x) => { 
       if (x > 3.14) "DoubleBox greater than pie !" 
       else if (x == 3.14) "DoubleBox with a pie !" 
       else "DoubleBox less than a pie !" 
    } 
    case _ => "What is it yaa ?" 
    }            

    useCase(Box("StringBoxxx")) //> res0: String = I found the StringBox! 
    useCase(Box("Whatever !")) //> res1: String = Some other StringBox 
    useCase(Box(true))   //> res2: String = Omg! its true BooleanBox ! 
    useCase(Box(false))   //> res3: String = its false BooleanBox :(
    useCase(Box(4))    //> res4: String = DoubleBox greater than pie ! 
    useCase(Box(3.14))   //> res5: String = DoubleBox with a pie ! 
    useCase(Box(2))    //> res6: String = DoubleBox less than a pie ! 
+0

예, 그게입니다. 고맙습니다. –

+0

환영합니다 .. :) – Shrey

관련 문제