수색…


지역 유형 유추

스칼라는 언어에 내장 된 강력한 유형 추론 메커니즘을 사용합니다. 이 메커니즘을 '로컬 형식 유추'라고합니다.

val i = 1 + 2                  // the type of i is Int
val s = "I am a String"        // the type of s is String
def squared(x : Int) = x*x     // the return type of squared is Int

컴파일러는 초기화 표현식에서 변수 유형을 유추 할 수 있습니다. 마찬가지로 메소드의 리턴 유형은 메소드 본문에서 리턴 된 유형과 같기 때문에 생략 할 수 있습니다. 위의 예제는 명시 적 형식 선언과 같습니다.

val i: Int = 1 + 2               
val s: String = "I am a String" 
def squared(x : Int): Int = x*x     

유형 유추 및 제네릭

스칼라 컴파일러는 다형 메소드가 호출되거나 일반 클래스가 인스턴스화 될 때 유형 매개 변수를 추론 할 수 있습니다.

case class InferedPair[A, B](a: A, b: B)

val pairFirstInst = InferedPair("Husband", "Wife")  //type is InferedPair[String, String]
    
// Equivalent, with type explicitly defined
val pairSecondInst: InferedPair[String, String] 
                      = InferedPair[String, String]("Husband", "Wife")  

위 형식 유추 형식은 Java 7에서 소개 된 Diamond Operator 와 유사합니다.

추론의 한계

스칼라 유형 추론이 작동하지 않는 시나리오가 있습니다. 예를 들어, 컴파일러는 메소드 매개 변수의 유형을 추론 할 수 없습니다.

def add(a, b) = a + b  // Does not compile
def add(a: Int, b: Int) = a + b // Compiles
def add(a: Int, b: Int): Int = a + b // Equivalent expression, compiles

컴파일러는 재귀 메서드의 반환 형식을 유추 할 수 없습니다.

// Does not compile
def factorial(n: Int) = if (n == 0 || n == 1) 1 else n * factorial(n - 1)
// Compiles
def factorial(n: Int): Int = if (n == 0 || n == 1) 1 else n * factorial(n - 1)

아무것도 유추하는 것을 막기.

이 블로그 게시물을 기반으로 합니다 .

다음과 같은 메소드가 있다고 가정 해보십시오.

  def get[T]: Option[T] = ???

제네릭 매개 변수를 지정하지 않고 호출하려고하면 Nothing 유추되지 않습니다. 실제 구현에는 그리 유용하지 않습니다. 그 결과는 유용하지 않습니다. 다음 해결책을 사용하면 NotNothing 컨텍스트 바인딩으로 인해 예상되는 형식을 지정하지 않고 메서드를 사용할 수 있습니다 (이 예제에서는 RuntimeClassNothing 아닌 ClassTags 경우 제외되지만 RuntimeClass 는 유추됩니다).

@implicitNotFound("Nothing was inferred")
sealed trait NotNothing[-T]

object NotNothing {
  implicit object notNothing extends NotNothing[Any]
  //We do not want Nothing to be inferred, so make an ambigous implicit
  implicit object `\n The error is because the type parameter was resolved to Nothing` extends NotNothing[Nothing]
  //For classtags, RuntimeClass can also be inferred, so making that ambigous too
  implicit object `\n The error is because the type parameter was resolved to RuntimeClass` extends NotNothing[RuntimeClass]
}

object ObjectStore {
  //Using context bounds
  def get[T: NotNothing]: Option[T] = {
    ???
  }
  
  def newArray[T](length: Int = 10)(implicit ct: ClassTag[T], evNotNothing: NotNothing[T]): Option[Array[T]] = ???
}

사용 예 :

object X {
  //Fails to compile
  //val nothingInferred = ObjectStore.get
  
  val anOption = ObjectStore.get[String]
  val optionalArray = ObjectStore.newArray[AnyRef]()
  
  //Fails to compile
  //val runtimeClassInferred = ObjectStore.newArray()
}


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow