2013-08-04 2 views
2

으로 한 평가, 성공 실패 :스칼라 추론 : 나는 스칼라에서 초보자있어 여기에 무슨 일이 생긴 것을 이해하지 못하는 중간 발

을 감안할 때 :

val reverse:Option[MyObject] = ... 

그리고 myObject.isNaire 반환 부울.

내가 할 경우 : 그것은 작동

val v:Option[Boolean] = reverse.map(_.isNaire) 
val b:Boolean = v.getOrElse(false) 

.

이제 내가 할 경우

val b:Boolean = reverse.map(_.isNaire).getOrElse(false) 

그것은 type mismatch: found Any, required Boolean


편집 컴파일 실패 : 감사 베릴륨, SSCCE함으로써, 나는 해설의 시작을 발견했다. 첫 번째 예에서 myObject는 Java 클래스이므로 isNaire는 java.lang.Boolean입니다. 내 암시 적 변환은이 설명을 투명하게 만들어야 설명이 여전히 환영받을 것이라고 생각했습니다.

class Test(val naire:java.lang.Boolean) 

class Other { 
    val testValue = Some(new Test(true)) 
    def mysteriousCompilationError:Boolean = testValue.map(_.naire).getOrElse(false) 
} 

참고 :

implicit def Boolean2boolean(x: java.lang.Boolean): Boolean = x.booleanValue 

그래서 첫 번째 경우 val v:Option[Boolean] = reverse.map(_.isNaire)에 컴파일러가 볼

java.lang.Boolean과 외모의 : ScalaCompiler는 java.lang.Boolean에서 scala.Boolean에 암시 적 변환이 년대 scala.Predef에서 2.10.2

+1

수정 된 버전을 컴파일 할 수 있으므로 [SSCE] (http://sscce.org/)를 제공하십시오. – Beryllium

+0

'false'는'java.lang.Boolean'의 값이 아니기 때문에 java.lang.Boolean을 map() 함수 리터럴의 scala.Boolean으로 변환하는 것이 더 낫습니다. 예를 들어, 'map (_. predicate) .getOrElse (false)'는 다음과 같이 간단하게 나타낼 수 있습니다 :'def mysteriousCompilationError : Boolean = testValue.map (_. naire == true) .getOrElse (false)' – swartzrock

답변

5

입니다 범위에있는 암시 적 메서드를 scala.Boolean으로 변환하면 편리하게는 scala.Predef에 있습니다. 당신이 두 번째 경우, testValue.map(_.naire).getOrElse(false) 야에서

, 컴파일러는이 순서대로 일을한다 :

  1. Ajava.lang.BooleanBscala.Boolean 이후 Any입니다 Option[Test] => Option[java.lang.Boolean]
  2. getOrElse[B >: A](default: => B): B>:java.lang.Boolean
  3. 되지 않는다 val b:Boolean, 컴파일러에서 Any에서로 암시 적 변환을 찾을 수 없습니다.

    def works:Boolean = testValue.map[Boolean](_.naire).getOrElse(false) 
    

    이것은 일반적인 문제입니다 :

이 주위에 얻을 수있는 유일한 방법은, java.lang.Boolean에서 scala.Boolean로 이동 scala.Predef에서 암시 적 변환을 사용하도록지도 작업 중에 컴파일러에게하는 것입니다 map에이어서 getOrElse이 자주 등장하기 때문에 자주 나타납니다.제대로 여분의 유형하지 않고이 문제를 해결하려면, 옵션을 통해 fold (catamorphism)를 사용 : 어떤 변환이 아래로 일반적인 유형이 없기 때문에 fold를 사용하여

def worksToo:Boolean = testValue.fold(false)(_.naire) 

당신이 몇 가지 추가 유형의 안전을 얻는다. 예를 들어, 당신은이 작업을 수행 할 수 없습니다

def failsTypeCheck = testValue.fold("test")(_.naire) 

를 컴파일러가이 아무 문제가 없지만 :

def passesTypeCheck = testValue.map(_.naire).getOrElse("test") 
+1

IntelliJ IDEA는 **'.exists (_. 술어)'**, 이것은 덧셈에'fold'를 사용하는 것보다 낫습니다! –

+0

@ 0__ 좋아, 나에게 똑같은 말을했다. 나는 눈치 채지 못했다. :) – Noah

0

java.lang.Booleanscala.Boolean는 동일하지 않습니다. 격차를 해소하려면 암시 ​​적 변환이 작업을 수행 할 수있는 위치를 제공해야합니다.

자바/스칼라 상호 운용성 이러한 유형의 문제 처리 할 수있는 몇 가지 패턴이 있습니다

  • 는 스칼라 측에서 사용하는 다른 방법이 할 수있는 상태인지


    을, 당신은 암시 적 값을 사용할 수 있습니다 클래스 :
object Container { 
    implicit class Test2Scala(val test: Test) extends AnyVal { 
    def naireForScala: Boolean = test.naire 
    } 
} 

class Other { 
    val testValue = Some(new Test(true)) 

    import Container._ 
    def mysteriousCompilationError: Boolean = 
    testValue.map(_.naireForScala).getOrElse(false) 
} 

이 실행시 추가 인스턴스를 필요로하지 않습니다. Java 클래스를 풍부하게하는 다른 방법을 제공합니다. 당신이 하위 클래스를 파생 할 수있는 경우


  • , 당신은 DummyImplicit를 사용하여 메소드의 이름을 보존 할 수 있습니다 :
class Test2(_naire: Boolean) extends Test(_naire) { 
    def naire(implicit di: DummyImplicit): Boolean = _naire 
} 

class Other { 
    val testValue = Some(new Test2(true)) 
    def mysteriousCompilationError: Boolean = 
    testValue.map(_.naire).getOrElse(false) 
} 

DummyImplicit는 다른 방법 서명을받을 필요합니다. 조금 까다 롭고 런타임에 추가 인스턴스가 필요하지만 Test2Test (OOP 측면에서)입니다.


  • 랩 스칼라 인스턴스의 자바 예 :
class TestWrapper(test: Test) { 
    def naire: Boolean = test.naire 
} 

class Other { 
    val testValue = Some(new TestWrapper(new Test(true))) 

    def mysteriousCompilationError: Boolean = 
    testValue.map(_.naire).getOrElse(false) 
} 

TestWrapperTest 아니지만, 그것은 간단합니다, 당신은 대리인을 추가해야 추가 인스턴스가 필요합니다.

관련 문제