복붙노트

[SCALA] 스칼라 케이스 클래스를 선언하는 단점은 무엇입니까?

SCALA

스칼라 케이스 클래스를 선언하는 단점은 무엇입니까?

아름다운, 불변의 데이터 구조를 많이 사용하고있는 거 코드를 작성하는 당신이 경우, 케이스 클래스는 하나 개의 키워드로 당신에게 무료로 다음의 모든을주는 신의 선물이 될 것으로 보인다 :

그러나이 경우 클래스로 불변의 데이터 구조를 정의의 단점은 무엇입니까?

이 클래스 또는 고객에 어떤 제한을합니까?

가 아닌 경우 클래스를 선호해야이 상황이 있습니까?

해결법

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

    1.하나의 큰 단점 : 사례 클래스가 케이스 클래스를 확장 할 수 없습니다. 즉, 제한입니다.

    하나의 큰 단점 : 사례 클래스가 케이스 클래스를 확장 할 수 없습니다. 즉, 제한입니다.

    완성도 나와 당신이 놓친 다른 장점 : 준수 직렬화 / 역 직렬화가 필요 만들기 위해 "새로운"키워드를 사용 없습니다.

    나는 가변 상태, 개인의 상태, 또는 어떤 상태 (예를 들어, 대부분의 단일 구성 요소)를 가지는 객체가 아닌 경우 클래스를 선호합니다. 다른 거의 모두를위한 케이스 클래스.

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

    2.먼저 좋은 비트 :

    먼저 좋은 비트 :

    기본적으로 모든의 불변

    예, 심지어 (사용 VAR) 당신이 그것을 필요로하는 경우에 대체 할 수 있습니다

    게터는 자동으로 정의

    추가하는 설정 PARAMS와 발에 의한 수업 가능

    점잖은 toString () 구현

    예, 매우 유용하지만, 필요한 경우 모든 클래스에 손으로 행할

    준수 equals ()와 hashCode ()

    쉬운 패턴 매칭과 결합,이 사람들이 경우 클래스를 사용하는 주된 이유는

    매칭) (적용된 방법 컴패니언 개체

    또한 가능한 추출기를 사용하여 모든 클래스에 손으로해야 할 일

    이 목록은 또한 스칼라 2.8에 와서 동네 짱 - 강력한 복사 방법, 최고의 물건 중 하나를 포함해야한다

    그런 나쁜, 케이스 클래스와 실제 제한의 소수에 불과하다 :

    연습하지만, 이것은 거의 문제가 없다. 적용 생성 방법의 변경 동작이 깜짝 사용자에게 보장 강하게 낙담한다, 그렇게 유일한 정당성의 유효성을 검사 입력 매개 변수입니다 - (복사를 사용하는 경우도 확인이 가능합니다) 가장 기본 생성자 몸을 이루어 작업

    사실, 그것은 여전히 ​​가능하지만 자체에 대한 사례 클래스는 후손을 위해. 하나 개의 일반적인 패턴은 트리의 리프 노드로 케이스 클래스를 사용하여, 특성의 클래스 계층 구조를 구축하는 것입니다.

    또한 밀봉 수정을 주목할 가치가있다. 이 수정과 특성의 서브 클래스가 동일한 파일에 선언해야합니다. 형질의 인스턴스에 대해 패턴 일치 할 때 모든 가능한 구체적인 하위 클래스를 검사하지 않은 경우, 컴파일러는 경고 메시지를 표시 할 수 있습니다. 케이스 클래스와 결합 될 때이 경고없이 컴파일하는 경우이 코드에서 당신에게 신뢰의 매우 높은 수준의 레벨을 제공 할 수 있습니다.

    실제 해결 방법은,이 많은 PARAMS으로 클래스를 학대 중지를 제외하지 :)

    때때로 언급 한 다른 제한 사항은 스칼라 (현재) (그러나 매개 변수로, 게으른 놈들처럼) 게으른 PARAMS을 지원하지 않는다는 것입니다. 이에 대한 해결 방법은별로 이름 PARAM을 사용하고 생성자에서 게으른 발에 할당하는 것입니다. 불행하게도,에 의해 이름 PARAMS는 컴파일러 생성 추출기를 나누기로 케이스 클래스와 함께 사용 된 기술의 존재를 방지 패턴 매칭과 함께 사용하지 마십시오.

    이것은 당신이 고기능 게으른 데이터 구조를 구현하려는 경우 관련, 희망 스칼라의 향후 릴리스에 게으른 PARAMS의 추가로 해결 될 것입니다.

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

    3.나는 TDD 원칙이 여기에 적용 생각 : 끝나지 디자인을한다. 당신이 경우 클래스로 뭔가를 선언 할 때, 당신은 많은 기능을 선언한다. 즉, 미래에 클래스 변경에 당신이 가지고있는 유연성을 감소합니다.

    나는 TDD 원칙이 여기에 적용 생각 : 끝나지 디자인을한다. 당신이 경우 클래스로 뭔가를 선언 할 때, 당신은 많은 기능을 선언한다. 즉, 미래에 클래스 변경에 당신이 가지고있는 유연성을 감소합니다.

    예를 들어, 경우 클래스는 생성자 매개 변수를 통해 equals 메소드가 있습니다. 당신이 평등 이러한 매개 변수의 일부를 무시하려는, 또는 비트 뭔가 다른 일을 먼저, 후자의 클래스를 쓸 수 있지만 때를 결정할 수 있음에 대해 상관하지 않을 수 있습니다. 그러나 클라이언트 코드는 경우 클래스 평등에 따라 평균 시간에 기록 될 수 있습니다.

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

    4.우리는 클래스의 경우 클래스 사이에서 선택해야 할 때 우리가 사용하는 수 - 마틴 오더 스키는 우리에게 스칼라에서 그의 물론 기능 프로그래밍 원리에 좋은 시작점 (패턴 매칭 강의 4.6)를 제공합니다. 스칼라 바이 예의 제 7 동일한 예를 포함한다.

    우리는 클래스의 경우 클래스 사이에서 선택해야 할 때 우리가 사용하는 수 - 마틴 오더 스키는 우리에게 스칼라에서 그의 물론 기능 프로그래밍 원리에 좋은 시작점 (패턴 매칭 강의 4.6)를 제공합니다. 스칼라 바이 예의 제 7 동일한 예를 포함한다.

    abstract class Expr {
      def eval: Int
    }
    
    class Number(n: Int) extends Expr {
      def eval: Int = n
    }
    
    class Sum(e1: Expr, e2: Expr) extends Expr {
      def eval: Int = e1.eval + e2.eval
    }
    

    또한, 새로운 생산성 클래스를 추가하면 기존 코드를 변경을 수반하지 않습니다

    class Prod(e1: Expr, e2: Expr) extends Expr {
      def eval: Int = e1.eval * e2.eval
    }
    

    반면에, 새로운 방법은 기존의 모든 클래스의 수정을 필요로 추가 할 수 있습니다.

    abstract class Expr { 
      def eval: Int 
      def print
    } 
    
    class Number(n: Int) extends Expr { 
      def eval: Int = n 
      def print { Console.print(n) }
    }
    
    class Sum(e1: Expr, e2: Expr) extends Expr { 
      def eval: Int = e1.eval + e2.eval
      def print { 
       Console.print("(")
       print(e1)
       Console.print("+")
       print(e2)
       Console.print(")")
      }
    }
    

    동일한 문제가 케이스 클래스를 해결했다.

    abstract class Expr {
      def eval: Int = this match {
        case Number(n) => n
        case Sum(e1, e2) => e1.eval + e2.eval
      }
    }
    case class Number(n: Int) extends Expr
    case class Sum(e1: Expr, e2: Expr) extends Expr
    

    새로운 방법을 추가하는 것은 지역의 변화이다.

    abstract class Expr {
      def eval: Int = this match {
        case Number(n) => n
        case Sum(e1, e2) => e1.eval + e2.eval
      }
      def print = this match {
        case Number(n) => Console.print(n)
        case Sum(e1,e2) => {
          Console.print("(")
          print(e1)
          Console.print("+")
          print(e2)
          Console.print(")")
        }
      }
    }
    

    새로운 생산성 클래스를 추가하는 것은 잠재적으로 모든 패턴 매칭을 변경할 필요합니다.

    abstract class Expr {
      def eval: Int = this match {
        case Number(n) => n
        case Sum(e1, e2) => e1.eval + e2.eval
        case Prod(e1,e2) => e1.eval * e2.eval
      }
      def print = this match {
        case Number(n) => Console.print(n)
        case Sum(e1,e2) => {
          Console.print("(")
          print(e1)
          Console.print("+")
          print(e2)
          Console.print(")")
        }
        case Prod(e1,e2) => ...
      }
    }
    

    videolecture 4.6 패턴 매칭에서 성적 증명서

    주의 사항 : 우리가 유일한 기준 같은 시작점처럼이를 사용하지 않아야합니다.

  5. ==============================

    5.나는 앨빈 알렉산더 6 장으로 스칼라 요리 책에서이 말을 인용하고있다 : 오브젝트.

    나는 앨빈 알렉산더 6 장으로 스칼라 요리 책에서이 말을 인용하고있다 : 오브젝트.

    이것은 내가이 책에서 흥미로운 발견 많은 것들 중 하나입니다.

    이 경우 클래스의 여러 생성자를 제공하기 위해,이 경우 클래스 선언이 실제로 무엇을하는지 아는 것이 중요합니다.

    case class Person (var name: String)
    

    당신은 스칼라 컴파일러는 경우 클래스, 예를 들면 생성하는 코드를 보면, 당신은 두 개의 출력 파일, 사람 $의 .class 및 Person.class를 만들어 볼 것을 볼 수 있습니다. 당신이 사람 $의 .class는은 javap 명령을 분해하면 그것이 많은 다른 사람들과 함께 방법을 적용 포함되어 있는지 볼 수 있습니다 :

    $ javap Person$
    Compiled from "Person.scala"
    public final class Person$ extends scala.runtime.AbstractFunction1 implements scala.ScalaObject,scala.Serializable{
    public static final Person$ MODULE$;
    public static {};
    public final java.lang.String toString();
    public scala.Option unapply(Person);
    public Person apply(java.lang.String); // the apply method (returns a Person) public java.lang.Object readResolve();
            public java.lang.Object apply(java.lang.Object);
        }
    

    또한 분해 Person.class가 포함 된 내용을 볼 수 있습니다. 이 같은 간단한 클래스의 경우, 추가로 20 개 메소드를 포함하고; 이 숨겨진 팽창은 일부 개발자의 경우 클래스처럼하지 않는 이유 중 하나입니다.

  6. from https://stackoverflow.com/questions/4653424/what-are-the-disadvantages-to-declaring-scala-case-classes by cc-by-sa and MIT license