복붙노트

[SCALA] 어떻게 경우 클래스의 인스턴스를 복제하고 스칼라에 하나의 필드를 변경하려면?

SCALA

어떻게 경우 클래스의 인스턴스를 복제하고 스칼라에 하나의 필드를 변경하려면?

하자 내가 페르소나, 다른 소셜 네트워크에 사람을 나타내는 경우 클래스가 말한다. 이 클래스의 인스턴스는 완전히 불변이며, 결국 Akka 배우에 의해 수정 될, 불변의 컬렉션에서 개최된다.

지금, 나는 많은 필드가있는 경우 클래스가, 그리고 내가 필드 중 하나,이 같은 업데이트해야합니다라는 메시지가 나타납니다 :

case class Persona(serviceName  : String,
                   serviceId    : String,
                   sentMessages : Set[String])

// Somewhere deep in an actor
val newPersona = Persona(existingPersona.serviceName,
                         existingPersona.serviceId,
                         existingPersona.sentMessages + newMessage)

공지 사항 나는 모든 필드, 비록 단 하나의 변화를 지정해야합니다. 복제 existingPersona에 대한 방법과 대체 단 하나 개의 필드가 변경되지 않는 모든 필드를 지정하지 않고 있습니까? 나는 특성으로 그 쓰기 내 모든 경우의 클래스를 사용할 수 있습니까?

페르소나였다 경우지도 같은 경우, 쉽게 할 수있을 것이다.

해결법

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

    1.이러한 사용에 정확히 전용 복사 방법의 경우 classcomes :

    이러한 사용에 정확히 전용 복사 방법의 경우 classcomes :

    val newPersona = existingPersona.copy(sentMessages = 
                       existingPersona.sentMessages + newMessage)
    
  2. ==============================

    2.2.8 이후, 스칼라의 경우 클래스의 마법을 위해 이름 / 기본 PARAMS을 활용 복사 방법이있다 :

    2.8 이후, 스칼라의 경우 클래스의 마법을 위해 이름 / 기본 PARAMS을 활용 복사 방법이있다 :

    val newPersona =
      existingPersona.copy(sentMessages = existing.sentMessages + newMessage)
    

    또한 단순화 사용에 페르소나의 방법을 만들 수 있습니다 :

    case class Persona(
      svcName  : String,
      svcId    : String,
      sentMsgs : Set[String]
    ) {
      def plusMsg(msg: String) = this.copy(sentMsgs = this.sentMsgs + msg)
    }
    

    그때

    val newPersona = existingPersona plusMsg newMsg
    
  3. ==============================

    3.

    existingPersona.copy(sentMessages = existingPersona.sentMessages + newMessage)
    
  4. ==============================

    4.볼품없는 라이브러리에 렌즈를 사용하는 것이 좋습니다 :

    볼품없는 라이브러리에 렌즈를 사용하는 것이 좋습니다 :

    import shapeless.lens
    
    case class Persona(serviceName  : String,
                       serviceId    : String,
                       sentMessages : Set[String])
    // define the lens
    val messageLens = lens[Persona] >> 'sentMessages 
    
    val existingPersona = Persona("store", "apple", Set("iPhone"))
    
    // When you need the new copy, by setting the value,
    val newPersona1 = messageLens.set(existingPersona)(Set.empty)
    // or by other operation based on current value.
    val newPersona2 = messageLens.modify(existingPersona)(_ + "iPad")
    
    // Results:
    // newPersona1: Persona(store,apple,Set())
    // newPersona2: Persona(store,apple,Set(iPhone, iPad))
    

    당신이 중첩 된 경우 수업을해야하는 경우에 또한,의 getter 및 setter 메소드 작성에 조금 지루한 될 수 있습니다. 이 렌즈 라이브러리를 사용하여 간단하게 할 수있는 좋은 기회가 될 것입니다.

    또한 다음을 참조하십시오 :

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

    5.난 당신이 중첩 된 경우 클래스에 깊이 값을 설정할 수 복잡한 렌즈를 수행하는 큰 라이브러리를 포함하지 않았다. 그것은이 scalaz 라이브러리에서 단 몇 줄의 코드입니다 밝혀 :

    난 당신이 중첩 된 경우 클래스에 깊이 값을 설정할 수 복잡한 렌즈를 수행하는 큰 라이브러리를 포함하지 않았다. 그것은이 scalaz 라이브러리에서 단 몇 줄의 코드입니다 밝혀 :

      /** http://stackoverflow.com/a/5597750/329496 */
      case class Lens[A, B](get: A => B, set: (A, B) => A) extends ((A) => B) with Immutable {
        def apply(whole: A): B = get(whole)
    
        def mod(a: A, f: B => B) = set(a, f(this (a)))
    
        def compose[C](that: Lens[C, A]) = Lens[C, B](
          c => this(that(c)),
          (c, b) => that.mod(c, set(_, b))
        )
    
        def andThen[C](that: Lens[B, C]) = that compose this
      }
    

    그런 다음 깊이가 복사 기능 내장 사용하는 것보다 훨씬 더 쉽게 중첩 된 값을 설정 렌즈를 만들 수 있습니다. 여기에 큰 세트에 링크되어있는 경우 내 라이브러리 사용이 많이 중첩 된 값을 설정한다는 것을 복합 렌즈.

  6. from https://stackoverflow.com/questions/7249396/how-to-clone-a-case-class-instance-and-change-just-one-field-in-scala by cc-by-sa and MIT license