2012-11-02 11 views
10

Jestem całkiem nowy w Scali i mam pytanie o najlepszy sposób skopiowania klasy sprawy przy zachowaniu danych pochodzących z cech. Na przykład, powiedzmy, że mam następujące:Scala: Kopiowanie klas przypadków z cechą

trait Auditing { 

    var createTime: Timestamp = new Timestamp(System.currentTimeMillis) 
} 

case class User(val userName: String, val email: String) extends Auditing 

val user = User("Joe", "[email protected]") 

Następnie chcę zrobić nową kopię z jednego parametru zmianie:

val user2 = user.copy(email = "[email protected]") 

Teraz, w powyższym przykładzie, createtime nieruchomość nie dostać skopiowane, ponieważ nie jest zdefiniowane w konstruktorze klasy Case użytkownika. Moje pytanie brzmi: zakładając, że przeniesienie createTime do konstruktora nie jest opcją, jaki jest najlepszy sposób na uzyskanie kopii obiektu User, która zawiera wartość z cechy?

Używam Scala 2.9.1

Dzięki z góry! Joe

+0

nie ma zbyt wiele możliwości przed sobą: albo ręcznie wdrożyć taką metodę, która będzie produkować kopie chcesz w deklaracji klasy 'użytkownik portu wypadku lub użyć Scala 2.10 makr do automatyzacji, które oferują. Druga opcja zdecydowanie nie będzie łatwym zadaniem dla początkujących. –

+1

@NikitaVolkov Jeśli byłbyś gotów dostarczyć mi/nam przykład, w jaki sposób zrobiłbyś to z makrami, byłoby to więcej niż świetne. –

+2

@mhs Dołączam do klubu. Jestem newbee w makrach, dlatego nie opublikowałem go jako odpowiedzi. Ale [tutaj jest jak] (http://stackoverflow.com/a/10397595/485115) Rozwiązałem bardzo podobne zadanie z api Toolbox. Przyjęta tam odpowiedź jest oparta na makrach, ale myślę, że nie obsługuje ona najnowszej wersji Scala. –

Odpowiedz

6

Można zastąpić metodę kopiowania tym zachowaniem.

case class User(val userName: String, val email: String) extends Auditing 
{ 
    def copy(userName = this.userName, email = this.email) { 
    val copiedUser = User(userName, email) 
    copiedUser.createTime = createTime 
    copiedUser  
    } 
} 
3

Chociaż nie widzę innego rozwiązania niż Reubena, nie rozumiem wymóg opuścić argumenty konstruktora nietknięte. To byłoby najbardziej naturalne rozwiązanie:

case class User(userName: String, email: String, 
    override val createTime:Timestamp = new Timestamp(System.currentTimeMillis)) 
     extends Auditing 

Jeśli nie chcesz, aby użytkownik mógł nadpisać createTime, nadal można używać:

case class User private (userName: String, email: String, 
    override val createTime:Timestamp) extends Auditing { 
    def this(userName: String, email: String) = 
    this(userName, email, new Timestamp(System.currentTimeMillis)) 
} 

Jedyną wadą jest to, że trzeba napisz new User("Joe", "[email protected]"), ponieważ główny konstruktor jest teraz prywatny.

0

Być może lepiej nie używać klasy przypadków. Możesz łatwo zaimplementować odpowiednią funkcjonalność . Poniższy kod implementuje żądaną metodę kopiowania, konstruktor bez nowego, ukrywa oryginalny konstruktor i tworzy ekstraktor, dzięki czemu można używać instrukcji User w instrukcjach case.

class User private(val userName: String, 
        val email: String, 
        val timeStamp: Timestamp = 
        new Timestamp(System.currentTimeMillis)) { 

    def copy(uName: String = userName, 
      eMail: String = email) = 
    new User(uName, eMail, timeStamp) 
} 

object User { 
    def apply(userName: String, email: String) = 
    new User(userName, email) 

    def unapply(u: User) = Some((u.userName, u.email, u.timeStamp)) 
} 
Powiązane problemy