2014-04-11 2 views
2

는 스칼라에서이 같은 방법 정의가 말 T의 유형에 따라?스칼라 패턴

Function1 대신에 다시 작성해야하고 패턴 일치가 필요합니까?

내가 해봤 다음하지만 때문에 형의 삭제에 작동하지 않습니다 어쩌면 추상적 인 유형

class A { 
    def x(fn: A => Unit): Unit = fn(this) 
} 

class B { 
    def y(fn: B => Unit): Unit = fn(this) 
} 

def handle[T](fn: Function1[T, Unit]): Unit = { 
    fn match { 
    case fnA: Function1[A, Unit] => 
     new A().x(fnA) 
    case fnB: Function1[B, Unit] => 
     new B().y(fnB) 
    } 
} 

를?

예상 출력을 인쇄
import scala.reflect.runtime.universe._ 

class A { 
    def x(fn: A => Unit): Unit = fn(this) 
    override def toString = "A" 
} 
class B { 
    def y(fn: B => Unit): Unit = fn(this) 
    override def toString = "B" 
} 

def handle[T : TypeTag](fn: Function1[T, Unit]): Unit = typeOf[T] match { 
    case t if t =:= typeOf[A] => new A().x(fn.asInstanceOf[Function1[A, Unit]]) 
    case t if t =:= typeOf[B] => new B().y(fn.asInstanceOf[Function1[B, Unit]]) 
} 

handle[A] { a: A => 
    println("It's " + a) 
} 
handle[B] { b: B => 
    println("It's " + b) 
} 

가 :

+0

'handle'의 서명을 변경하는 것이 좋습니까? 그리고 A와 B를 바꿀까? – Beryllium

답변

0

은 내가 TypeTag 인스턴스를 사용하여 답을 찾은 것 같아 사람이 더 나은 솔루션이있는 경우

It's A 
It's B 

이 알려 :)

1

typeclass로이를 수행 할 수 있으며 반사 또는 유형 태그가 필요하지 않습니다.

// Typeclass defines things that can be handled 
    trait Handleable[T] { 
    def handle(fn: T => Unit) 
    } 

    // Two typeclass instances, one for A and one for B 
    implicit object AHandleable extends Handleable[A] { 
    def handle(fn: A => Unit) = new A().x(fn) 
    } 

    implicit object BHandleable extends Handleable[B] { 
    def handle(fn: B => Unit) = new B().y(fn) 
    } 

    // implicitly grab the instance for whichever type we are using (A, B...) 
    def handle[T](f: T => Unit)(implicit h: Handleable[T]) = h.handle(f) 
    //or equivalently: 
    //def handle[T: Handleable](f: T => Unit) = implicitly[Handleable[T]].handle(f) 

    handle((a: A) => println(a))     //> A 
    handle((b: B) => println(b))     //> B 

A와 B는 유용한 공통 수퍼 클래스가 없으므로 (원래는 하나만 줄 수는 없다고 가정하고 있습니다!) typeclass 패턴을 사용하면 원래 클래스를 수정하지 않고도 공통적 인 수퍼 타이트를 "볼트로 고정"할 수 있습니다 ("ad-hoc 다형성 ").

handle() 메서드를 수정하지 않고 나중에 추가 인스턴스 (예 : C, D 등)를 추가로 지원할 수 있습니다.

+0

깔끔하게 보입니다. 리플렉션보다 성능이 좋을 것이라고 가정합니다. 감사! –

관련 문제