使用 Scala 2.11.12。
分散在我的代碼庫中,我有一個這樣的案例類:
case class Landscape(
north: Sight,
east: Sight,
south: Sight,
west: Sight
) {
def toList: List[Sight] = List(north, east, south, west)
def isIdyllic: Boolean = north.isPastoral && east.isPastoral && south.isPastoral && west.isPastoral
}
(帶有自定義案例類Sight)和相應的伴隨物件:
object Landscape {
def fromSeq(s: Seq[Sight]): Landscape = {
require(s.length == 4)
Landscape(
north = s(0),
east = s(1),
south = s(2),
west = s(3)
)
}
def pickByBeautifulSouth(scape1: Landscape, scape2: Landscape): Landscape = {
if (scape1.south.beauty > scape2.south.beauty) scape1 else scape2
}
}
事實證明,擁有相似的型別會很有用,所以我創建了一個通用案例類:
case class Compass[A](
north: A,
east: A,
south: A,
west: A
) {
def toList: List[A] = List(north, east, south, west)
}
帶有相應的伴隨物件:
object Compass {
def fromSeq[A](s: Seq[A]): Compass[A] = {
require(s.length == 4)
Compass[A](
north = s(0),
east = s(1),
south = s(2),
west = s(3)
)
}
}
顯然isIdyllic,pickByBeautifulSouth對于任意型別沒有意義A。現在我想做Landscape一個豐富的Compass,所以我不必再定義toList和fromSeq了Landscape。
我知道我做不到
case class Landscape(
north: Sight,
east: Sight,
south: Sight,
west: Sight
) extends Compass[Sight] {
def isIdyllic: Boolean = north.isPastoral && east.isPastoral && south.isPastoral && west.isPastoral
}
因為不可能進行個案繼承。我也不能讓 Compass[A] 成為這樣的特征:
trait Compass[A]{
def north: A
def east: A
def south: A
def west: A
def toList: List[A] = List(north, east, south, west)
}
因為那樣我會打破fromSeq使用Compass' 欄位及其應用方法的方式。
我也想過使用隱式類
implicit class LandscapeOps(ls: Compass[Sight]) {
def isIdyllic: Boolean = ls.north.isPastoral && ls.east.isPastoral && ls.south.isPastoral && ls.west.isPastoral
}
和我的代碼庫中的型別別名
type Landscape = Compass[Sight]
但是,這樣我會通過丟失Landscape的 apply 方法再次破壞我的代碼。而且我也不知道怎么加pickByBeautifulSouth。
長話短說:我正在尋找一種方法
- 使用,所以我不必
Landscape重復和CompasstoListfromSeq - 通過對代碼庫的最小更改來實作這一點,即
Landscape(sight1, sight2, sight3, sight4)并且Landscape.copy(west=someSight)應該仍然可以作業,以及Landscape.pickByBeautifulSouth(scape1, scape2)
uj5u.com熱心網友回復:
不確定我是否理解所有的限制,但是.. 為什么不是特征Compass[T]和子型別Landscape
trait Compass[A] {
val north: A
val east: A
val south: A
val west: A
def toList: List[A] = List(north, east, south, west)
}
case class Landscape(
north: Sight,
east: Sight,
south: Sight,
west: Sight
) extends Compass[Sight] {
def isIdyllic: Boolean = north.isPastoral && east.isPastoral && south.isPastoral && west.isPastoral
}
那么整個景觀物件仍然有效
object Landscape {
def fromSeq(s: Seq[Sight]): Landscape = {
require(s.length == 4)
Landscape(
north = s(0),
east = s(1),
south = s(2),
west = s(3)
)
}
def pickByBeautifulSouth(scape1: Landscape, scape2: Landscape): Landscape =
???
}
uj5u.com熱心網友回復:
所以這是我最終得到的一個最小的作業示例:
case class Sight() {
def isPastoral: Boolean = true
def beauty: Int = 5
}
case class Compass[A](
north: A,
east: A,
south: A,
west: A
) {
def toList: List[A] = List(north, east, south, west)
}
object Compass {
def fromSeq[A](s: Seq[A]): Compass[A] = {
require(s.length == 4)
Compass[A](
north = s(0),
east = s(1),
south = s(2),
west = s(3)
)
}
}
object LandscapeModule {
type Landscape = Compass[Sight]
val Landscape = Compass
implicit class LandscapeOps(ls: Landscape) {
import ls._
def isIdyllic: Boolean = north.isPastoral && east.isPastoral && south.isPastoral && west.isPastoral
}
object LandscapeOps {
def pickByBeautifulSouth(scape1: Landscape, scape2: Landscape): Landscape = {
if (scape1.south.beauty > scape2.south.beauty) scape1 else scape2
}
}
}
object HowToUseIt {
import LandscapeModule.{Landscape, LandscapeOps}
val sight = Sight()
val sights: Seq[Sight] = Seq.fill(4)(sight)
val landscape: Landscape = Landscape(north = sight, east = sight, south = sight, west = sight)
val landscapeFromSeq = Landscape.fromSeq(sights)
LandscapeOps.pickByBeautifulSouth(landscape, landscapeFromSeq)
}
這樣我只需要在我的代碼庫中改變兩件事:
- 進口:
import LandscapeModule.{Landscape, LandscapeOps}而不是import Landscape - 呼叫景觀的自定義工廠方法,而不是
fromSeq:LandscapeOps.pickByBeautifulSouth而不是Landscape.pickByBeautifulSouth
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/486221.html
