2012-05-11 5 views
1

일 동안 암시 적 변환 문제를 해결하기 위해 노력했지만 어떻게 든 잘못 이해하고 있습니다. 나는 암시를 다루는 다른 모든 질문을 읽었지 만 나는 아직도 그 문제가 무엇인지 이해하지 못한다.자바 인터페이스를 구현하는 일반적인 특성에 대한 스칼라 암시 적 변환

예를 들어

, 이제 (T는 간결 객체를 확장)과 같은 Java 인터페이스를 살펴 보자 : 주석에 명시된 바와 같이

case class A() 
case class B() extends A 
case class C() 
case class D() extends C 

trait Persistable[DTOType <: A, EntityType <: C] { 
    // this would be implemented somewhere else 
    private def doPersist(source: EntityType): EntityType = source 

    // this does not implement the method from the Java interface 
    private def realPersist(source: DTOType)(implicit view: DTOType => EntityType): EntityType = doPersist(source) 

    // this DOES implement the method from the Java interface, however it throws: 
    // error: No implicit view available from DTOType => EntityType. 
    def persist(source: DTOType): EntityType = realPersist(source) 
} 

case class Persister() extends Persistable[B, D] with JPersistable[B] 

object Mappings { 
    implicit def BToD(source: B): D = D() 
} 

object Test { 
    def main(args: Array[String]) { 

    import Mappings._ 
    val persisted = Persister().persist(B()) 
    } 
} 

:

스칼라
public interface JPersistable<T extends Object> { 
    public T persist(T entity); 
} 

, 나는 다음을 수행 , 나는 컴파일 타임에 예외를 얻는다. 제 질문은 다음과 같습니다.

1) 명시 적으로 doRealPersist에서 암시 적 변환을 지정해야하는 이유는 무엇입니까?

trait Persistable[DTOType <: A, EntityType <: C] { 
    // this would be implemented somewhere else 
    private def doPersist(source: EntityType): EntityType = source 

    def persist(source: DTOType): EntityType = doPersist(source) 
} 

그러나이 경우에도 변환이 수행 될 것으로 예상했습니다.

2) 실제 메서드 호출 (val persisted = Persister().persist(B()))이 아닌 persist에서 컴파일이 실패하는 이유는 무엇입니까? EntityType과 DTOType의 실제 유형이 알려진 첫 번째 장소 여야합니다. 맞습니까?

3) 달성하려는 작업을 수행하는 더 좋은 방법이 있습니까? 다시 말하지만, 이것은 내가하려고하는 실제적인 것이 아니라 충분히 가깝습니다.

이 질문이 무식하고 사전에 도움을 주시면 감사하겠습니다.

답변

2

내에서 변환을 사용할 수 있도록해야합니다. persist은 비밀리에 암시 적 변환이 필요한 realPersist이 필요하다는 것을 외부에서 알지 못하기 때문에 외부에서 암묵적으로 전달할 수 없습니다. 이 모든 것은 JPersistable을 고려하지 않고도 실패합니다.

당신은 예를 들어 특성의 방법으로

implicit def view: DTOType => EntityType 

을 추가하고 그 다음에 컴파일됩니다. (realPersist도 삭제할 수 있습니다.)

그런 다음 해당보기 집합을 가져 오는 방법이 필요합니다. 할 수 있습니다.

case class Persister()(implicit val view: B => D) extends Persistable[B,D] 

그리고 모두 훌륭합니다. 합니다 (implicit val 만족 특성의 implicit def에게.)

하지만 지금은 당신이 더 큰 문제가 : 자바 인터페이스 서명 은 스칼라 서명 일치하지 않습니다. 등가 스칼라

trait JPersistable[T <: Object] { def persist(t: T): T } 

persist 소요와 같은 형식을 반환하는 방법을 참조입니까? 그리고 이 스칼라 클래스의이 아닌지 확인하십시오. 그것은 작동하지 않을 것입니다! 따라서 여기서 성취하려고하는 것을 정확히 재고해야합니다. 어쩌면 암시 적 변환을 사용할 수있게 만들고 싶을 수도 있습니다. 메서드에 전달하지 마십시오!그리고 스칼라가 암시 적 변환을 적용하여 DTOType에서 EntityType으로 매핑하는 persist을 가지고 있다고 생각하지만 실제로는 Java 인터페이스에 필요한 EntityType에서 EntityType으로 변환해야합니다.


편집 :

trait JPer[T] { def persist(t: T): T } 
class A 
case class B() extends A 
class C 
case class D() extends C 
trait Per[Y <: C] extends JPer[Y] { 
    private def doIt(y: Y): Y = y 
    def persist(y: Y) = doIt(y) 
} 
case class Perer() extends Per[D] // "with JPer" wouldn't add anything! 
object Maps { implicit def BtoD(b: B): D = D() } 
object Test extends App { 
    import Maps._ 
    val persisted = Perer().persist(B()) 
} 

에주의 유형을 사용하는 예를 들어, 여기에 그냥 표준 암시 적 변환을 사용하여 게시 된 어떤 작업 버전입니다! (누가 B이고 누가 D을 가지며 어느 방향으로 변환해야합니까?)

+0

렉스 Rex. 아직도 혼란스러운 것은 Predef implicits ('byte2short'와 같은)를 위해서 당신이 변환을 사용하기를 원한다면 그 추상 def를 지정할 필요가 없다는 것입니다. 나는 전환이 가능할 것이라고 예상했다. .. 음, 암시 적으로. 특히 내 질문에 1, 유형을 알고 변환을 해결하기 위해 scala를 기대합니다. 최소한 필자가 예로 든 Persister의 범위에'Mappings._'을 가져 오면 암묵적인 def를 다시 구현할 필요가 없다는 것을 나는 기대할 것이다. 그것은 정확히 내가 잘못하고있는 것이 무엇인지 내게 미스테리가 남아있다 ... – LeChe

+0

@LeChe - 나는 "외부 암시 적 변환을해라."라는 조언을 사용하여 제 답변을 업데이트했습니다. –

+0

물론, 나는 그런 바보 야! 특성이 A-tree를 알아야하는 이유는 무엇입니까? 변환은 완전히 투명해야합니다. 젠장, 지금 바보 같아. 당신의 설명에 진심으로 감사드립니다. – LeChe