2013-03-24 5 views
6

내가이 잘 컴파일이일반 매개 변수와 함께 구조 유형을 사용하려면 어떻게해야합니까?

type HasApply1 { 
    def apply[A, R](argument: A): R 
} 

모두의 동반자 개체와 일치하는 구조 유형을 정의 할 수 있지만,이 개 경우 클래스

case class StringCaseClass(argument: String) 

case class IntCaseClass(argument: Int) 

이 나는 ​​그것을 사용하려고하면 이

def method(caseClass: HasApply1) { 
    // whatever 
} 

method(StringCaseClass) 

처럼 컴파일러 오류가 발생합니다

found : StringCaseClass.type 
required: WithApply1 
      (which expands to) AnyRef{def apply[A, R](string: A): R} 

이 작업을 수행 할 수있는 방법이 있습니까? 구조 유형을 A 및 R에 대한 구체적인 유형을 재정의하면 올바르게 컴파일되지만 유연성이 손실됩니다.

+0

, 나는 이와 같은 방법을 만들고 싶습니다,이 경우 클래스 동반자 당신은 단순히이 작업을 수행 할 수 있도록 이미는 해당 FunctionN 특성을 구현합니다입니다 방법 A [caseClass : HasApply1, a : A] = caseClass.apply (a)' – shinyhappydan

답변

9

@ aloiscochard의 코멘트가 거의 있습니다. `정의 : 그가 언급하는 것을 잊었다 것은

자세한 설명이 들어
scala> case class StringCaseClass(argument: String) 
defined class StringCaseClass 

scala> case class IntCaseClass(argument: Int) 
defined class IntCaseClass 

scala> def method[A, R](caseClass: A => R, a: A) = caseClass(a) 
method: [A, R](caseClass: A => R, a: A)R 

scala> method(StringCaseClass, "foo") 
res0: StringCaseClass = StringCaseClass(foo) 

scala> method(IntCaseClass, 23) 
res1: IntCaseClass = IntCaseClass(23) 
+0

이것이 내가 원하는 바로 그 것이다. 내가 물어 본 질문에 대한 진정한 대답은 당신이 할 수 없다는 것입니다. 그러나 이것은 저에게 효과적입니다. – shinyhappydan

+0

와우 마일즈, 훌륭합니다. 나는 어제로 돌아갈 수있는 기회가 없었지만, 그것이 내가 생각해 냈던 것보다 낫다! +1! – coltfred

0

methodStringCaseClass의 인스턴스를 전달하지 않았습니다. 당신이 통과 한 것은 StringCaseClass의 동반자 객체입니다 (케이스 클래스에 대해 자동으로 생성됩니다).

시도해보십시오 (method(StringCaseClass("dummy"))).

3

일반적으로 은 매우으로 구조적 타이핑을 피해야합니다. JVM의 한계로 인해 호출이 리플렉션 호출로 변환됩니다. scala 2.10 구조 유형을 사용하기 시작하면 컴파일 타임에 경고가 발생합니다 (플래그를 사용하여 비활성화 할 수 있음).

상속 계층 구조를 공유하지 않는 클래스에 기능을 추가하는 일반적인 방법을 찾고 있다면 유형 클래스를 사용할 수 있습니다. 난 당신이 달성하려는 모르겠어요 다시

createRFromA(1) // This gives a Blah2 
createRFromA("1") // This gives a Blah1 

, 그러나 아마 무엇을 할 수 있습니다 :

trait CanCreateRFromA[A,R]{ 
    def createNew(a:A): R 
} 

implicit object CanCreateBlahFromInt extends CanCreateRFromA[Int,Blah2]{ 
    def createNew(i:Int):Blah2 = new Blah2(i) 
} 


implicit object CanCreateBlah1FromString extends CanCreateRFromA[String,Blah1]{ 
    def createNew(s:String):Blah1 = new Blah1(s) 
} 

case class Blah1(something:String) 
case class Blah2(something:Int) 

def createRFromA[A,R](a:A)(implicit tc:CanCreateRFromA[A,R])= tc.createNew(a) 

그런 다음 당신이 호출 할 수 있습니다 : 여기

빠른 예제 당신은 타입 클래스를 원하고 훨씬 더 빠를 것입니다.

+2

가벼운 대안은 생성하는 대신 Function1 [A, R]'(또는 A => R') 유형을 사용합니다 CanCreateRFrom 형질. –

+0

@ 콜트 프레드 (@coltfred) 내가하려는 일에 대한 더 명확한 설명을 원하면 내 의견을 참조하십시오. 나는 수술 비용을 걱정하지 않는다. – shinyhappydan