2014-07-25 6 views
2

내가 비슷한 두 경우 클래스스칼라 받아들이는 일반적인 클래스

나는 그들 중 하나를 가지고 같은 경우 클래스의 목록을 반환하는 일반적인 fucntion를 작성해야
abstract class MainClass 
case class Acc(x:String, y:String) extends MainClass 
case class Bcc(x:String, y:String) extends MainClass 

있습니다

def f1[T <: MainClass ]():List[T]={ 
val o1 = new Acc("sss","ddd").asInstanceOf[T] 
List(o1) 
} 

유일한 문제는 내가 유형 클래스 "Acc"를 하드 코딩한다는 것입니다. 내 질문은 어떻게 f1 메서드를 Acc 또는 Bcc 대신 일반 클래스 T를 인스턴스화 할 수 있습니다.

감사합니다.

답변

1

런타임 중에 ClassTag를 사용하여 클래스에 대한 메타 정보를 유지할 수 있습니다. ClassTag 솔루션 런타임 반사에 의존, 당신을 위해 일 수 있지만

import scala.reflect._ 


abstract class MainClass 
case class Acc(x:String, y:String) extends MainClass 
case class Bcc(x:String, y:String) extends MainClass 

object Boot extends App { 



    def f1[T <: MainClass : ClassTag ]():List[T]={ 
    val o1 = classTag[T].runtimeClass.getConstructor(classOf[String], classOf[String]).newInstance("sss","ddd").asInstanceOf[T] 
    List(o1) 
    } 

val list = f1[Acc] 

} 
+0

달콤한 감사합니다. – CruncherBigData

+0

난 downvoter, FWIW 아니에요. 나는이 질문에 대한 부당한 대답이라고 생각하지 않는다. 단지 그것이 가장 좋은 대답이라고 생각하지 않는다. –

+1

저는 downvoter입니다. 런타임 리플렉션이 특별히 사소한 경우를 피하는 유스 케이스에서는 적당하다고 생각하지 않습니다. –

11

는 코드 냄새, 그리고 실제로 진짜 문제에 당신을 얻을 수 있습니다. 당신이 (다른 코드를 사용하여 사용자 또는 사람 중 하나 정의)이 같은 새로운 서브 클래스로 끝날 가정 : 누군가가 f1[Ccc]를 씁니다 - 그리고 방법 서명에는 표시가 없을 때

case class Ccc(x: String, y: String, i: Int) extends MainClass 

은 이제 그들은 안 -이 프로그램은 런타임에 NoSuchMethodException과 충돌합니다.

이런 종류의 일을하는 데 훨씬 안전한 방법이 있으며, 상용구 작성이 약간 필요하지만 코드를 사용하는 사람들 (자신 포함)에게는 투명합니다. 당신은 꽤 명확하게 당신의 f1를 작성할 수

implicit def AccFromStrings: MainClassFromStrings[Acc] = 
    new MainClassFromStrings[Acc] { 
    def apply(x: String, y: String) = Acc(x, y) 
    } 

implicit def BccFromStrings: MainClassFromStrings[Bcc] = 
    new MainClassFromStrings[Bcc] { 
    def apply(x: String, y: String) = Bcc(x, y) 
    } 

그리고 지금 :

trait MainClassFromStrings[T <: MainClass] { 
    def apply(x: String, y: String): T 
} 

이 그럼 당신은 어떤 종류의 클래스 인스턴스를 작성 : 먼저 MainClass의 일부 특정 서브 클래스의 인스턴스를 생성하는 방법에 대해 설명 type class를 정의 :

다음
def f1[T <: MainClass](implicit fs: MainClassFromStrings[T]) = 
    List(fs("sss", "ddd")) 

그리고 :

scala> f1[Acc] 
res0: List[Acc] = List(Acc(sss,ddd)) 

scala> f1[Bcc] 
res1: List[Bcc] = List(Bcc(sss,ddd)) 

f1[Ccc]을 시도하면 좋은 컴파일 타임 오류가 발생합니다.

타입 클래스는 스칼라 (표준 라이브러리 포함)에서 꽤 널리 사용됩니다. "type classes" in Scala에 대한 스택 오버플로를 검색하면 많은 예제와 토론이 나타납니다.

+0

암시 적 변환을 컴패니언 개체에 넣고 인수에 삽입 할 수 있으므로 암시 적 범위가 제한 될 수 있습니다. –

+0

@Cloudtech : 암묵적인 변환은 여기에 없으며 "인수에 삽입"한다는 것이 무슨 뜻인지 모르겠지만 인스턴스를 'MainClassFromStrings'컴패니언 객체에 넣을 수는 있습니다. 대답을 간단하게 유지하는 것. –

관련 문제