2015-02-26 12 views
12

Mam klasę abstrakcyjną, którą rozszerzam i tworzę liczne klasy przypadków. Teraz chcę skopiować instancje tych klas przypadków, zmieniając tylko pierwszy parametr, więc używam metody klasy "copy".Case to case in Scala

Ponieważ muszę to zrobić dla wszystkich klas przypadków, które zostały rozszerzone ze wspólnej abstrakcyjnej klasy, zamiast robić to dla wszystkich, starałem się uczynić ją ogólną i uczynić abstrakcyjną klasę klasą przypadku.

Potem Scala daje mi to:

case case klasę Octopus ma przodka organizm, ale sprawa do przypadku dziedziczenia jest zabronione. Aby przezwyciężyć to ograniczenie, użyj ekstraktorów do dopasowania wzorca w węzłach innych niż liść.

Kod:

abstract class Organism(legs: Int) 
case class Octopus(override val legs: Int, weight: Double, ...) 
case class Frog(override val legs: Int, ...) 
def clone(o: Organism) = o.copy(legs = -1) 

To jest to, co chcę robić. Ale jeśli nie mogę wykonać metody clone, będę musiał wykonać kopię dla obu Octopus & Frog.

Wszelkie sugestie, aby zmniejszyć tę szczegółowość?

Odpowiedz

10

Nie można generalnie streścić metod klasy "copy". Sugeruję użyciu obiektywów z bezkształtnej lub Monocle:

trait Organism { def legs: Int } 
// monocle @Lenses uses a macro to generate lenses 
@Lenses case class Octopus(override val legs: Int, weight: Double, ...) 
    extends Organism 
@Lenses case class Frog(val legs: Int, ...) extends Organism 

def clone[O <: Organism](o: O, legsLens: Lens[O, Int]): O = 
    legsLens.set(-1)(o) 

val myOctopus = Octopus(8, 2.4, ...) 
val myFrog = Frog(2, ...) 

// use the generated Lenses 
val cloneOctopus: Octopus = clone(myOctopus, Octopus.legs) 
clone(myFrog, Frog.legs) 
0

używając tylko standardowe Scala nie ma takich rodzajowe metoda kopiowania na abstrakcyjnym (super) Klasa: jak by to wiedzieć, jak wszystkie podklasy mogą być sklonowane/skopiowane? Zwłaszcza, że ​​nowe podklasy mogą być dodawane w przyszłości.

Według mojej wiedzy, dwa główne podejścia do wdrożenia takiej metody abstrakcyjne są:

1) dokonać funkcję mecz sprawę na wszystkich podklas:

def clone(o: Organism) = o match { 
    case o: Octopus => o.copy(legs = -1) 
    case f: Frog => f.copy(legs = -1) 
} 

Potem za każdym razem nowa podklasa jest dodano, należy dodać w tej funkcji. Jest to najbardziej odpowiednie do użytku z sealed abstract class.

2) dodać metodę makeClone do abstrakcyjnego API (nazwa clone są zarezerwowane):

abstract class Organism(legs: Int){ 
    def makeClone(legNumber: Int): Organism 
} 
case class Octopus(legs: Int, weight: Double) extends Organism(legs) { 
    def makeClone(legNumber: Int) = this.copy(legs = legNumber) 
} 

pamiętać, że funkcja w (1) zawsze zwraca Organism tu metodę Octopus.makeClone zwracającą Octopus .