답변:
나는 이것이 이미 요청되었다고 생각했지만, 그렇다면 "관련된"바에서 그 질문은 명백하지 않다. 그래서 여기 있습니다 :
바인딩보기는 어떤 종류의 사용을 가능하게하는 스칼라에 도입 된 메커니즘이었다 A
것처럼 그것이 어떤 종류의했다 B
. 일반적인 구문은 다음과 같습니다.
def f[A <% B](a: A) = a.bMethod
다시 말해, type의 객체에서 메소드를 호출 할 수 있도록 available A
로 암시 적으로 변환해야 합니다 . 표준 라이브러리 (스칼라 2.8.0 이전)에서 가장 많이 사용되는 뷰 바운드는 다음 과 같습니다.B
B
A
Ordered
def f[A <% Ordered[A]](a: A, b: A) = if (a < b) a else b
하나는 변환 할 수 있기 때문에 A
로 Ordered[A]
하고 있기 때문에 Ordered[A]
방법을 정의 <(other: A): Boolean
, 나는 표현을 사용할 수 있습니다 a < b
.
양해하여 주시기 바랍니다 뷰 경계가되지 않습니다 당신이 그들을 피해야한다.
컨텍스트 범위는 Scala 2.8.0에서 도입되었으며, 일반적으로 Haskell 유형 클래스가 제공하는 기능을보다 장황하게 표현하는 코드 패턴 인 소위 유형 클래스 패턴 과 함께 사용됩니다 .
뷰 바운드는 단순 유형 (예 :)과 함께 사용할 수 있지만 A <% String
컨텍스트 바운드에는 위와 같은 매개 변수화 된 유형이 필요 Ordered[A]
하지만와는 다릅니다 String
.
컨텍스트 바운드 는 뷰 바운드의 암시 적 변환 대신 암시 적 값을 설명합니다 . 일부 유형 의 경우 사용 가능한 유형의 내재 된 값이 있음을 선언하는 데 사용됩니다 . 구문은 다음과 같습니다.A
B[A]
def f[A : B](a: A) = g(a) // where g requires an implicit value of type B[A]
사용 방법이 명확하지 않기 때문에 뷰 바운드보다 혼란 스럽습니다. 스칼라 사용법의 일반적인 예는 다음과 같습니다.
def f[A : ClassManifest](n: Int) = new Array[A](n)
Array
매개 변수화 된 유형에 대한 초기화는 ClassManifest
유형 삭제 및 배열의 비 삭제 특성과 관련된 특별한 이유로 사용할 수 있어야 합니다.
라이브러리에서 또 다른 매우 일반적인 예는 조금 더 복잡합니다.
def f[A : Ordering](a: A, b: A) = implicitly[Ordering[A]].compare(a, b)
여기서는 클래스가 메소드를 정의하는 implicitly
유형 중 하나 인 원하는 암시 적 값을 검색하는 데 사용됩니다 .Ordering[A]
compare(a: A, b: A): Int
우리는 이것을 아래에서 수행하는 다른 방법을 볼 것입니다.
뷰 바운드와 컨텍스트 바운드가 모두 정의에 따라 암시 적 매개 변수로 구현된다는 것은 놀라운 일이 아닙니다. 실제로, 내가 보여준 구문은 실제로 일어나는 일에 대한 구문 설탕입니다. 그들이 어떻게 설탕을 제거하는지 아래를보십시오 :
def f[A <% B](a: A) = a.bMethod
def f[A](a: A)(implicit ev: A => B) = a.bMethod
def g[A : B](a: A) = h(a)
def g[A](a: A)(implicit ev: B[A]) = h(a)
따라서 자연스럽게 전체 구문으로 작성할 수 있으며 컨텍스트 범위에 특히 유용합니다.
def f[A](a: A, b: A)(implicit ord: Ordering[A]) = ord.compare(a, b)
뷰 바운드는 주로 라이브러리 형식 의 포주를 활용하는 데 주로 사용되며 ,이를 통해 원래 형식을 반환하려는 상황에서 기존 클래스에 메서드를 "추가"합니다. 어떤 식 으로든 해당 유형을 반환 할 필요가 없으면 뷰 바운드가 필요하지 않습니다.
뷰 바운드 사용의 고전적인 예는 처리 Ordered
입니다. 참고 Int
아니다은 Ordered
, 예를 들어, 비록 암시 적 변환이 있습니다. 이전에 제공된 예제는 변환되지 않은 유형을 반환하므로 뷰 바운드가 필요합니다.
def f[A <% Ordered[A]](a: A, b: A): A = if (a < b) a else b
이 예제는 뷰 바운드없이 작동하지 않습니다. 그러나 다른 유형을 반환하려는 경우 더 이상 뷰 바인딩이 필요하지 않습니다.
def f[A](a: Ordered[A], b: A): Boolean = a < b
매개 변수를에 전달하기 전에 여기에서 필요한 경우 변환이 발생 f
하므로 f
알 필요가 없습니다.
게다가 Ordered
, 라이브러리의 가장 일반적인 사용은 취급 String
하고 Array
그들이 스칼라 컬렉션 것처럼, 자바 클래스있는. 예를 들면 다음과 같습니다.
def f[CC <% Traversable[_]](a: CC, b: CC): CC = if (a.size < b.size) a else b
하나의 뷰 경계없이이 작업을 수행하려고 경우의 반환 형식은 String
것 WrappedString
, 유사에 대한 (스칼라 2.8) Array
.
형식이 반환 형식의 형식 매개 변수로만 사용되는 경우에도 마찬가지입니다.
def f[A <% Ordered[A]](xs: A*): Seq[A] = xs.toSeq.sorted
컨텍스트 바운드는 주로 Haskell의 유형 클래스에 대한 참조 로 typeclass pattern으로 알려진 것에 사용됩니다 . 기본적으로이 패턴은 일종의 암시 적 어댑터 패턴을 통해 기능을 사용 가능하게하여 상속에 대한 대안을 구현합니다.
전형적인 예는 Scala 2.8 's Ordering
이며 Ordered
Scala의 라이브러리 전체 를 대체 합니다. 사용법은 다음과 같습니다.
def f[A : Ordering](a: A, b: A) = if (implicitly[Ordering[A]].lt(a, b)) a else b
일반적으로 다음과 같이 작성된 것을 볼 수 있습니다.
def f[A](a: A, b: A)(implicit ord: Ordering[A]) = {
import ord.mkOrderingOps
if (a < b) a else b
}
Ordering
기존 연산자 스타일을 가능하게하는 내부의 일부 암시 적 변환을 활용 합니다. 스칼라 2.8의 또 다른 예는 다음과 Numeric
같습니다.
def f[A : Numeric](a: A, b: A) = implicitly[Numeric[A]].plus(a, b)
더 복잡한 예는의 새로운 컬렉션 사용법 CanBuildFrom
이지만 이미 그것에 대해 매우 긴 답변이 있으므로 여기서는 피할 것입니다. 그리고 앞에서 언급했듯이 ClassManifest
구체적인 유형없이 새 배열을 초기화하는 데 필요한 사용법이 있습니다.
타입 클래스 패턴으로 묶인 컨텍스트는 문제를 분리 할 수 있기 때문에 자신의 클래스에서 훨씬 더 많이 사용될 수 있습니다. 반면 좋은 디자인으로 코드에서 뷰 바운드를 피할 수 있습니다. ).
오랜 시간 동안 가능했지만 컨텍스트 범위 사용은 실제로 2010 년에 시작되었으며 이제는 스칼라의 가장 중요한 라이브러리 및 프레임 워크에서 어느 정도 발견되었습니다. 그러나 그 사용법의 가장 극단적 인 예는 스칼라 즈 라이브러리로, Haskell의 강력한 기능을 스칼라에 제공합니다. 타입 클래스 패턴을 읽어서 사용할 수있는 모든 방법을 익히는 것이 좋습니다.
편집하다
관심있는 관련 질문 :