2016-07-25 1 views
2

나는 제네릭과 같이가는 특성이 있습니다스칼라는 일반 유형에서 구체적인 클래스의 인스턴스를

object MyTraitFactory { 
    def apply[T](param1: Boolean, param2: Boolean): MyTrait[T] = { 
    // based on the type of T, I would like to instantiate sub types 
    } 
} 

I :

trait MyTrait[T] { 
    def doSomething(elems: Seq[T]) 
} 

그때 그 정의를 다음과 같이가는 객체 공장을 예를 들면 다음과 같은 구체적인 구현이 있습니다.

class MyStringTrait extends MyTrait[String] 

class MyIntTrait extends MyTrait[Int] 

이제는 내 객체 팩토리에 입력하고 해당 구현을 인스턴스화합니다. 어떤 제안?

답변

3

이것은 암시적인 typeclass를 사용하여 스칼라에서 해결할 수 있습니다. 당신의 유형 각각에 대한 구체적인 구현과 공장의 특성을 만듭니다

object MyTraitFactory { 

    def apply[T](param1: Boolean, param2: Boolean)(implicit factory: MyTraitCreator[T]): MyTrait[T] = { 
    // call the typeclass create method 
    factory.create(param1, param2) 
    } 

    // factory trait 
    trait MyTraitCreator[T] { 
    def create(param1: Boolean, param2: Boolean): MyTrait[T] 
    } 

    // provide an implicit factory object for the specific types: 
    object MyTraitCreator { 

    implicit object MyStringTraitCreator extends MyTraitCreator[String] { 
     override def create(param1: Boolean, param2: Boolean): MyTrait[String] = { 
     // create the String type here 
     new MyStringTrait 
     } 
    } 

    implicit object MyIntTraitCreator extends MyTraitCreator[Int] { 
     override def create(param1: Boolean, param2: Boolean): MyTrait[Int] = { 
     // create the Int type here 
     new MyIntTrait 
     } 
    } 
    } 
} 

스칼라는 암시 적 매개 변수를 사용하여 typeclass을 "숨 깁니다". 그러나 이것이 작동하려면 암시 ​​적 팩토리 객체를 컴파일러에서 implicits (예 : MyTraitCreator의 동반 객체)를 찾는 어딘가에 유지해야합니다. 패턴은 implicit이 없어도 작동하지만 각 호출마다 구체적인 팩토리를 제공하는 호출자가 필요합니다.

이 솔루션에는 많은 보일러 플레이트 코드가 포함되어 있지만 컴파일 타임에 정적으로 작동하며 유형 삭제가 발생하지 않습니다. 심지어 문법적 인 설탕이 스칼라에 들어 있습니다 :

def apply[T: MyTraitCreator](param1: Boolean, param2: Boolean): MyTrait[T] = { 
    // call the typeclass create method 
    implicitly[MyTraitCreator[T]].factory.create(param1, param2) 
} 
관련 문제