2011-03-11 4 views
2

나의 이해는 형 분산 다음과 같은 경우에 사용된다는 점이다 :입/출력 매개 변수를 제외한 유형 분산의 다른 용도는 무엇입니까?

  • 제네릭 형식 GG 방법의 인수의 형태로 나타납니다 매개 변수 T1를 입력이있는 경우, G반올림T1 일 수 있습니다. GG 방법 (또는 ctor에) 임의의 반환 값의 형태로 나타나는 타입 파라미터 T2을 가지면

  • 다음 GT2공변 수있다.

내가 위의 문장에서을해야 할 수 있습니다 교체하면? 동형 및 반동 변이를 사용하는 다른 사례가 있습니까? 언제 그리고 왜 당신의 유형을 공동 또는 반 차별로 만드나요? 스펙 인용

답변

3

는 4.5 차이 주석 :

분산 주석 파라미터 유형의 인스턴스에 대하여 하위 유형으로 어떻게 변하는지를 나타낸다 (§3.5.2). '+'분산은 공변 (covariant) 의존성을 나타내며, '-' 분산은 반동적 종속성을 나타내고, 누락 분산은 은 불변의 종속성을 나타냅니다. 분산 주석은 주석 매개 변수가 형식 매개 변수를 바인딩하는 형식 또는 클래스에 으로 나타나는 방식을 제한합니다. 유형 정의 유형 T [tps] = S 또는 유형 선언 유형 T [tps]> : L < : U 유형 매개 변수 + '는 공 변하는 위치에만 나타나야하고 '- ' 반공 위치에 나타난다.

따라서 유형 매개 변수는 기본적으로 불변으로 간주됩니다. 이것을 원한다면 형식 매개 변수에 공동 또는 반의어로 명시 적으로 주석을 달아야합니다 ( ). 또한 전혀 사용되지 않는 유형 매개 변수에 분산 주석을 사용하는 것이 합법적입니다 (유용하지는 않지만). 예 는 :


scala> class A[+T, -S] {def myMethod(s: String) = println(s)} 
defined class A 

scala> class A2[T] {def myMethod(t: T) = println(t)} 
defined class A2 

scala> class A3[-T] {def myMethod(t: T) = println(t)} 
defined class A3 

scala> val a1 = new A2[Any] 
a1: A2[Any] = [email protected] 

scala> val a2: A2[Int] = a1 
:6: error: type mismatch; 
found : A2[Any] 
required: A2[Int] 
     val a2: A2[Int] = new A2[Any] 

scala> val a3 = new A3[Any] 
a3: A3[Any] = [email protected] 

scala> val a4: A3[Int] = a3 
a5: A3[Int] = [email protected] 

예에서 contravariant 인 클래스 A3에 분산 주석, A3 [없음] 인스턴스 A4로부터 할당을 A3 [지능, 의 서브 타입 인 것으로 간주된다 만든다 ~ 3 법적. 분산 주석을 사용하지 않으면 실패합니다.

+0

답변 해 주셔서 감사합니다. 유스 케이스와 베스트 프랙티스에 대해 묻고 있다는 점을 분명히하지 못했습니다. 나는 지금 질문을 편집했다. – Michael

+0

좋아, 그 말이 맞는, 그리고 지금 내 대답은 더 이상 의미가되지 않습니다,하지만 어쨌든 개선하기 위해 다른 사람들을 위해 그것을 떠날거야. –

3

상황이 그렇게 간단하지 않습니다. 때로는 분산이 전혀 이해가 안되기 때문에 클래스를 불변으로 유지하면됩니다.

또한 분산은 사용 체인을 따라 토글됩니다. 예 :

class A[+T] 
class B[-T] { 
    def f(x: A[T]) {} 
} 

class C[+T] { 
    def g(x: B[T]) {} 
} 

또는 몇 가지 줄로 설명 할 수있는 간단한 것은 아닙니다.스칼라의 강력한 분산 실행이 매우 유용한 주된 이유는 무엇입니까? 요즘 Java의 분산을 사용하는 대부분의 코드가 미묘한 버그를 가지고 있다고 확신합니다.

+0

답변 해 주셔서 감사합니다. contravariance가 유용 할 때 사례 (사용 사례)를 제공해 주시겠습니까? 예를 들어, 나는 Funtion [+ X, -Y]가 인수 타입에서 반올림 적이라는 것을 알고 있습니다. 내 질문은 _ 우리가 사용할 수있을 때 _ 유용한 이유입니다. – Michael

+0

@Misha http://stackoverflow.com/questions/5279539/covariance-and-contravariance-considerations-when-designing/5280098#5280098을 참조하십시오. –

+0

** 수정 : ** 함수 [-X, + Y]입니다. 즉 함수의 인수 유형은 반 변형이고 결과 유형은 공변입니다. – Michael

1

이 오래된 질문을 해봅시다. 공분산과 반 차별의 사용 중 하나는 하한선을 통해 Generic에 약간의 제한을 두는 것입니다 : (공분산) 및 상한선 < : (반공 변성). 사용법은 다음 코드 스 니펫에서 볼 수 있습니다. 주제에 관한 내 자신의 blog입니다.

abstract class Animal (animalType:String) 

    class HasFourLegs(animalType:String) extends Animal(animalType){ 
     def move=println(this+" walking on four legs") 
    } 

    class HasTwoLegs(animalType:String) extends Animal(animalType){ 
     def move=println(this+" walking on Two legs") 
    } 

    case class Dog(animalType:String) extends HasFourLegs(animalType) 
    case class Ostrich(animalType:String) extends HasTwoLegs(animalType) 

     def moveOn4legs[T<:HasFourLegs](animal:T)= animal.move 
     val dog = Dog("dog") 
     val ostrich=Ostrich("ostrich") 
     moveOn4legs(dog) 
     /* 
     moveOn4legs(ostrich) 
     error: inferred type arguments [this.Ostrich] do not conform to method moveOn4legs's type parameter bounds [T <: this.HasFourLegs] 
     moveOn4legs(ostrich) 
    ^
     */ 
     println 

    class AnimalMovement [+T]{ 
     def movement[U>:T](animal:U)=println(animal+" walking on Two legs!!!") 
    } 

     val moveLikeTwoLegs=new AnimalMovement[HasTwoLegs]() 
     moveLikeTwoLegs.movement(ostrich) 
     moveLikeTwoLegs.movement(dog) 
관련 문제