복붙노트

[SCALA] 스칼라의 경우 클래스 상속

SCALA

스칼라의 경우 클래스 상속

나는 Squeryl 기반으로하는 응용 프로그램이 있습니다. 나는 복사 방법이 편리 찾을 주로하기 때문에, 사례 클래스로 내 모델을 정의합니다.

나는 엄격하게 관련된 두 가지 모델이있다. 필드는 같은 많은 작업이 공통으로되어 있으며, 그들은 같은 DB 테이블에 저장한다. 하지만 두 경우 중 하나에 의미가 어떤 행동이있다, 또는이 두 경우 모두에서 의미가 있지만 다르다.

지금까지 난 단지 모델의 종류를 구별하는 플래그, 하나의 경우 클래스를 사용하고있다는 IF와 모델의 시작의 종류에 따라 달라 모든 방법. 이 성가신이며, 매우 안전 입력하지.

내가 뭘하고 싶은 요소를 상위 케이스 클래스의 일반적인 행동과 필드를하고 두 실제 모델이 상속 있습니다. 그러나, 지금까지의 내가 이해, 사례 클래스에서 상속하는 것은 스칼라의 눈살을 찌푸리게되고, 서브 클래스 자체가 케이스 클래스 (나의 경우) 인 경우에도 금지되어 있습니다.

해결법

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

    1.코드 중복없이 케이스 클래스 상속을 피하는 나의 선호하는 방법은 다소 분명하다 : (추상) 기본 클래스 공통를 만들 :

    코드 중복없이 케이스 클래스 상속을 피하는 나의 선호하는 방법은 다소 분명하다 : (추상) 기본 클래스 공통를 만들 :

    abstract class Person {
      def name: String
      def age: Int
      // address and other properties
      // methods (ideally only accessors since it is a case class)
    }
    
    case class Employer(val name: String, val age: Int, val taxno: Int)
        extends Person
    
    case class Employee(val name: String, val age: Int, val salary: Int)
        extends Person
    

    개별 특성에 더 세분화 된 그룹 속성 싶은 경우 :

    trait Identifiable { def name: String }
    trait Locatable { def address: String }
    // trait Ages { def age: Int }
    
    case class Employer(val name: String, val address: String, val taxno: Int)
        extends Identifiable
        with    Locatable
    
    case class Employee(val name: String, val address: String, val salary: Int)
        extends Identifiable
        with    Locatable
    
  2. ==============================

    2.이 많은 것에 흥미있는 주제이기 때문에, 내가 여기에 도움이 되거 수 있습니다.

    이 많은 것에 흥미있는 주제이기 때문에, 내가 여기에 도움이 되거 수 있습니다.

    다음과 같은 방법으로 갈 수있다 :

    // You can mark it as 'sealed'. Explained later.
    sealed trait Person {
      def name: String
    }
    
    case class Employee(
      override val name: String,
      salary: Int
    ) extends Person
    
    case class Tourist(
      override val name: String,
      bored: Boolean
    ) extends Person
    

    예, 필드를 복제해야합니다. 그렇지 않으면, 단순히 다른 문제 사이에서 올바른 평등을 구현하는 것이 가능하지 않을 것입니다.

    그러나 중복 방법 / 기능에 필요하지 않습니다.

    몇 가지 속성의 중복 당신에게 중요성의 많은 경우, 정규 클래스를 사용하지만 잘 맞는 FP를하지 않는 것을 기억하십시오.

    다른 방법으로는 상속 대신 구성을 사용할 수 있습니다 :

    case class Employee(
      person: Person,
      salary: Int
    )
    
    // In code:
    val employee = ...
    println(employee.person.name)
    

    구성은 유효하고 당신은뿐만 아니라 고려해야 소리 전략이다.

    그리고 경우에 당신은 무엇을 밀봉 특성 수단을 궁금해 - 그것은 단지 동일한 파일에 확장 할 수있는 일이다. 즉,이 경우 클래스는 위의 동일한 파일에 있어야합니다. 이것은 철저한 컴파일러 검사 수 있습니다 :

    val x = Employee(name = "Jack", salary = 50000)
    
    x match {
      case Employee(name) => println(s"I'm $name!")
    }
    

    오류를 제공합니다 :

    warning: match is not exhaustive!
    missing combination            Tourist
    

    어떤 정말 유용합니다. 지금 당신은 사람 (사람)의 다른 유형에 대처하는 것을 잊지 않을 것입니다. 이것은 본질적으로 스칼라에서 옵션 클래스가하는 일입니다.

    그것은 당신에게 문제가되지 않는 경우, 당신은 비 봉인하고 자신의 파일에 경우 클래스를 던질 수있다. 그리고 아마도 구성과 함께 할 것입니다.

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

    3.케이스 클래스는 값 객체, 어떤 속성을 변경하지 않고 등호와 비교 될 수있다 즉 개체에 대한 완벽하다.

    케이스 클래스는 값 객체, 어떤 속성을 변경하지 않고 등호와 비교 될 수있다 즉 개체에 대한 완벽하다.

    그러나 상속의 존재 구현 동등한 오히려 복잡하다. 두 클래스를 고려 :

    class Point(x : Int, y : Int)
    

    class ColoredPoint( x : Int, y : Int, c : Color) extends Point
    

    정의 (빨간색 1,4 등) ColorPoint에 따른 포인트 (1,4) 동일해야한다 그래서 그들은 결국 같은 포인트입니다. (파란색 1,4) ColorPoint 그래서 또한 포인트 (1,4) 동일해야한다, 그렇지? 그러나 (빨간색 1,4) 물론 ColorPoint해야 같지 ColorPoint (1,4, 파란색), 서로 다른 색상을 가지고 있기 때문에. 당신이 가고, 평등 관계의 하나 개의 기본적인 속성 분류됩니다.

    최신 정보

    당신은 다른 답변에 설명 된대로 많은 문제를 해결 특성에서 상속을 사용할 수 있습니다. 훨씬 더 유연한 대안은 사용 유형 클래스에 종종있다. 스칼라의 타입 클래스는 유용 무엇을 참조하십시오? 또는 http://www.youtube.com/watch?v=sVMES4RZF-8

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

    4.이러한 상황에서 I 대신 사용 조성물 경향 상속 즉

    이러한 상황에서 I 대신 사용 조성물 경향 상속 즉

    sealed trait IVehicle // tagging trait
    
    case class Vehicle(color: String) extends IVehicle
    
    case class Car(vehicle: Vehicle, doors: Int) extends IVehicle
    
    val vehicle: IVehicle = ...
    
    vehicle match {
      case Car(Vehicle(color), doors) => println(s"$color car with $doors doors")
      case Vehicle(color) => println(s"$color vehicle")
    }
    

    분명히 당신은보다 정교한 계층 구조와 일치를 사용할 수 있지만 희망이 당신에게 아이디어를 제공합니다. 키는 경우 클래스가 제공하는 중첩 된 추출기를 활용하는 것입니다

  5. from https://stackoverflow.com/questions/12705309/scala-case-class-inheritance by cc-by-sa and MIT license