복붙노트

[SCALA] 왜 배열의 불변하지만,리스트는 공변?

SCALA

왜 배열의 불변하지만,리스트는 공변?

예를 들면 이유는 무엇입니까

val list:List[Any] = List[Int](1,2,3)

작동하지만

val arr:Array[Any] = Array[Int](1,2,3)

(배열은 불변이기 때문에) 실패합니다. 이 디자인 결정 뒤에 원하는 효과는 무엇인가?

해결법

  1. ==============================

    1.그것은 다른 유형의 안전을 깰 것 때문에. 그렇지 않다면, 당신은 이런 식으로 뭔가를 할 수있을 것입니다 :

    그것은 다른 유형의 안전을 깰 것 때문에. 그렇지 않다면, 당신은 이런 식으로 뭔가를 할 수있을 것입니다 :

    val arr:Array[Int] = Array[Int](1,2,3)
    val arr2:Array[Any] = arr
    arr2(0) = 2.54
    

    컴파일러는 그것을 잡을 수 없습니다.

    당신은 지능없는 무언가를 추가 할 수 있도록 반면에, 목록, 불변

  2. ==============================

    2.리스트는 불변과 배열은 변경할 수 있기 때문입니다.

    리스트는 불변과 배열은 변경할 수 있기 때문입니다.

  3. ==============================

    3.차이는 어레이 가변 동안리스트는 불변이다.

    차이는 어레이 가변 동안리스트는 불변이다.

    가변성이 분산을 결정 이유를 이해 목록의 변경 가능한 버전을 고려하는 -의이 MutableList를 호출 할 수 있습니다. 기본 클래스 동물 고양이와 개라는 이름이 개 서브 클래스 : 우리는 또한 몇 가지 예를 들어 유형의 사용을 만들 수 있습니다.

    trait Animal {
      def makeSound: String
    }
    
    class Cat extends Animal {
      def makeSound = "meow"
      def jump = // ...
    }
    
    class Dog extends Animal {
      def makeSound = "bark"
    }
    

    공지 고양이가 개보다 1 방법 (점프)를 가지고있다.

    그런 다음, 동물의 변경 가능한 목록을 허용하고 목록을 수정하는 함수를 정의 :

    def mindlessFunc(xs: MutableList[Animal]) = {
      xs += new Dog()
    }
    

    당신이 기능에 고양이의 목록을 전달하면 이제 끔찍한 일들이 일어날 것입니다 :

    val cats = MutableList[Cat](cat1, cat2)
    val horror = mindlessFunc(cats)
    

    우리는 부주의 한 프로그래밍 언어를 사용한 경우,이 컴파일시 무시됩니다. 우리는 다음과 같은 코드를 사용하여 고양이의 목록에 액세스 그럼에도 불구하고, 우리의 세계는 붕괴되지 않습니다 :

    cats.foreach(c => c.makeSound)
    

    그러나 우리는이 작업을 수행하는 경우 :

    cats.foreach(c => c.jump)
    

    런타임 오류가 발생합니다. 컴파일러 불평 때문에 스칼라와 같은 코드를 작성하는 것은 방지된다.

  4. ==============================

    4.제공하는 일반적인 대답은 유형의 안전을 끊을 공분산과 함께 그 가변성이다. 컬렉션의 경우,이 근본적인 진리로 간주 될 수있다. 그러나 이론은 실제로 제네릭 형식, 목록 및 배열과 같은뿐만 아니라 컬렉션에 적용, 우리는 시도하고 모두의 가변성에 대한 이유가 없습니다.

    제공하는 일반적인 대답은 유형의 안전을 끊을 공분산과 함께 그 가변성이다. 컬렉션의 경우,이 근본적인 진리로 간주 될 수있다. 그러나 이론은 실제로 제네릭 형식, 목록 및 배열과 같은뿐만 아니라 컬렉션에 적용, 우리는 시도하고 모두의 가변성에 대한 이유가 없습니다.

    진짜 대답은 하위 유형과 상호 작용하는 방식 기능 유형과 관련이있다. 짧은 이야기는 형식 매개 변수는 반환 형식으로 사용하는 경우, 그것은 공변입니다. 타입 파라미터가 인수 형태로 사용되는 반면에, 만약 그것이 contravariant이다. 그것은 반환 형식으로, 인수 유형으로 모두를 사용하는 경우, 그것은 불변이다.

    배열에 대한 문서에서 살펴 보자 [T]. 보기에 두 가지 분명한 방법은 검색 및 업데이트에 대한 것들에 대한 있습니다 :

    def apply(i: Int): T
    def update(i: Int, x: T): Unit
    

    제 T 내의 인수 유형 중에 첫 번째 방법에서, T는 복귀 형이다. 분산 결정 합니 규칙은 T 그러므로 불변이어야.

    이 공변 왜 우리는 목록에 대한 문서를 비교할 수 있습니다 [A]를 볼 수 있습니다. 혼동, 우리는 배열을위한 방법 [T] 유사하다이 방법을 찾을 것입니다 :

    def apply(n: Int): A
    def ::(x: A): List[A]
    

    A는 모두 반환 형식으로, 인수 유형으로 사용되기 때문에, 우리는 T가 배열 [T]입니다처럼 불변해야 할 것으로 예상됩니다. 그러나, 배열 [T]와 달리 문서의 :: 유형에 대해 우리에게 거짓말을한다. 거짓말이 방법이 가장 통화에 대한 충분한이지만, 우리는이 방법에 대한 설명서를 확장하여 "전체 서명"를 클릭하면 A의 분산을 결정하기 위해 충분하지 않습니다, 우리는 진실을 표시됩니다 :

    def ::[B >: A](x: B): List[B]
    

    그래서 실제로 인수 형식으로 표시되지 않습니다. 대신에, B는 (A의 모든 수퍼 될 수 있음) 인수의 형태이다. 정말 공변 될 수 있도록이은에 어떤 제한을 두지 않습니다. 인수 유형으로있다 목록 [A]에 대한 모든 방법은 유사한 거짓말이다 (이러한 방법은 [사용 사례]로 표시되기 때문에 우리가 말할 수 있습니다.)

  5. from https://stackoverflow.com/questions/6684493/why-are-arrays-invariant-but-lists-covariant by cc-by-sa and MIT license