2014-07-01 3 views
1

현재 프로젝트의 일부에는 데이터베이스에 연결된 형식의 변환과 Json을 통해 결과를 클라이언트에 직렬화 할 때 사용되는 제네릭 형식이 포함됩니다. 현재 스칼라에서 구현 된 형식은 형식 유추를 사용하여 스칼라 TypeTag 이용한 변환, 모든 경우의 클래스는 응용 프로그램 내에서 내부적으로 정의 입력으로개체 변환에 대한 형식 유추에 대한 설명

def Transform[A: TypeTag](objects:Seq[A]):Seq[Children] = typeOf[A] match { 
    case pc if pc =:= typeOf[ProductCategory] => 
    TransformProductCategory(objects.asInstanceOf[Seq[ProductCategory]]) 

    case pa if pa =:= typeOf[ProductArea] => 
    TransformProductArea(objects.asInstanceOf[Seq[ProductArea]]) 

    case pg if pg =:= typeOf[ProductGroup] => 
    TransformProductGroup(objects.asInstanceOf[Seq[ProductGroup]]) 

    case psg if psg =:= typeOf[ProductSubGroup] => 
    TransformProductSubGroup(objects.asInstanceOf[Seq[ProductSubGroup]]) 

    case _ => 
    throw new IllegalArgumentException("Invalid transformation") 
} 

유형은 예를 들어, 사용했을

case class ProductCategory(id: Long, name: String, 
          thumbnail: Option[String], 
          image:Option[String], 
          sequence:Int) 

이 방식은 순간에 적합하지만, 케이 't f 잠재적으로 더 많은 DB 유형이 추가 될 때 기능적이거나 확장 가능합니다. 나는 또한 유형이 이미 주장 된대로 asInstanceOf을 중복 사용해야한다고 생각합니다. 나의 제한된 내포 된 지식은 변형을 수행하기 위해 대신 사용될 수 있으며 위의 Transform[A: TypeTag](objects:Seq[A]):Seq[Children] 메소드의 필요성을 완전히 제거 할 수 있음을 암시합니다. 아니면 내가 대신 사용해야했던 다른 접근 방식이 있을까요?

답변

1

당신은이 같은 특성 정의 할 수 있습니다 : 다음 마지막으로

object Transformer { 
    implicit val forProduct = new Transformer[ProductCategory] { 
    def transformImpl(x: Seq[ProductCategory]) = ... 
    } 
    ... 
} 

그리고 :

trait Transformer[A] { 
    def transformImpl(x: Seq[A]): Seq[Children] 
} 

이 그럼 당신은 어떤 경우 정의 할 수 있습니다 당신은 정의해야합니다, 바람직하게는

def transform[A: Transformer](objects:Seq[A]): Seq[Children] = 
    implicitly[Transformer[A]].transformImpl(objects) 

당신의 Transformer 개체 또는 해당 개체에있는 암시 적 인스턴스 귀하의 카테고리 수업.

+0

사람들이 왜 def transform [A : Transformer] (objects : Seq [A])를 선호하는지 이해하지 못합니다. Seq [Children] = 암시 적으로 [Transformer [A]]. 이상 def transform [a] (객체 : Seq [A]) (암시 적 t : Transformer [A]) = t.transformImpl (객체)'... 강제적으로 '암시 적으로 장기적으로 끊임없이 아주 오래되어야합니다. 그렇다면 스칼라가 자동으로 그렇게하지 않는 이유는 무엇입니까? –

1

나는 그러나 어쨌든

을 해결책을 가지고 있습니다, 당신의 프로그램이 정확히 작동하도록되어 방법을 잘 모르겠어요, 나 당신의 변환 중 자수성가 한 타입이나 라이브러리에서 가져온 일이 있는지 어떻게 알 수 있습니까

뭔가 match는 정말 좋은 (당신이 당신과 함께 데이터를 가지고해야하는 경우), 당신은 아마도 경우 클래스에 그들 모두를 포장 할 수 수동으로 입력 데이터의 유형을 확인하는 것보다 그래서 오히려 case classes

또는 경우 객체 (그렇지 않은 경우)

이 같은 것을 할 수있는 방법 : 케이스 클래스에 모든 것을 포장하여

// this code assumes ProductCategory, ProductArea, etc. 
// all extends the trait ProductType 
def Transform(pType: ProductType): Seq[Children] = pType match { 
    case ProductCategory(objects) => TransformProductCategory(objects) 
    case ProductArea(objects)  => TransformProductArea(objects) 
    case ProductGroup(objects)  => TransformProductGroup(objects) 
    case ProductSubGroup(objects) => TransformProductSubGroup(objects) 
} 

, 당신은 너무 오래대로 (경우에 클래스가 아니라 당신이 함께 데려 할 데이터의 유형을 정확히 지정할 수 데이터) 모두 같은 클래스/특성에서 상속, 당신은 괜찮을

그리고 ProductType가 기본 케이스가 필요하지 않습니다 확장하는 클래스의 작은 소수가 이후

,없는 기본 경우가 때문에!

또 다른 이점은 무한히 확장 할 수 있다는 것입니다. 더 많은 사례와 사례 클래스를 추가하십시오!

이 솔루션을 사용하려면 코드를 많이 리팩토링해야하므로 코드를 작성하기 전에 염두에 두어야합니다.

관련 문제