這就是你將如何做這種事情的情況下,這3種特徵是密封的。如果他們願意擴展,它可能會變得更加複雜。
歸結爲以下幾點。您有Fancy
特徵,其中A
和B
兩種輸入類型,以及一種輸出類型Out
。您可以定義隱式實例,以便在A
和B
均爲ReturnsOne
,Out
將爲ReturnsOne
的情況下。在所有其他情況下,您將回退到默認情況下的優先級較低(因爲否則您將得到多義性錯誤),其中Out
總是ReturnsMany
。
scala> :paste
// Entering paste mode (ctrl-D to finish)
sealed trait ReturnCount
sealed trait ReturnsMany extends ReturnCount
sealed trait ReturnsOne extends ReturnCount
sealed trait Fancy[A, B] {
type Out <: ReturnCount
}
object Fancy extends LowerPriority {
type Aux[A,B,Out1 <: ReturnCount] = Fancy[A,B] { type Out = Out1 }
implicit def returnsOne: Fancy.Aux[ReturnsOne,ReturnsOne,ReturnsOne] =
new Fancy[ReturnsOne,ReturnsOne] { type Out = ReturnsOne }
}
trait LowerPriority {
implicit def returnsMany[A,B]: Fancy.Aux[A,B,ReturnsMany] =
new Fancy[A,B] { type Out = ReturnsMany }
}
class Query[R <: ReturnCount] {
def join[R2 <: ReturnCount](q: Query[R2])(implicit fancy: Fancy[R,R2]): Query[fancy.Out] = ???
}
// Exiting paste mode, now interpreting.
defined trait ReturnCount
defined trait ReturnsMany
defined trait ReturnsOne
defined trait Fancy
defined object Fancy
defined trait LowerPriority
defined class Query
scala> :type new Query[ReturnsOne].join(new Query[ReturnsOne])
Query[ReturnsOne]
scala> :type new Query[ReturnsOne].join(new Query[ReturnsMany])
Query[ReturnsMany]
scala> :type new Query[ReturnsMany].join(new Query[ReturnsMany])
Query[ReturnsMany]
scala> :type new Query[ReturnsMany].join(new Query[ReturnsOne])
Query[ReturnsMany]
在真實的場景中你Fancy
可能還需要一個join
方法,其中將包含實際的實現,你Query#join
方法委託:
class Query[R <: ReturnCount] {
def join[R2 <: ReturnCount](q: Query[R2])(implicit fancy: Fancy[R,R2]): Query[fancy.Out] =
fancy.join(this, q)
}
This blog可能是一個很好的起點,以瞭解更多關於這樣的模式。
如果''''R'''的類型爲'ReturnsOne''',那麼我需要'''R2'''來知道查詢返回的結果數量。如果R的類型爲'''ReturnsMany''',那麼你是對的,它不會產生任何影響,因爲它將是''''ManyMany'''無論如何 – shayan
爲什麼由'R2'確定的結果數量和不是'R'?這裏'R'的一般用法是什麼? –
@YuvalItzchakov它由R3確定,R3需要R和R2來決定。我正在尋找這個隱含的參數,它使用R和R2來解析R3,使其更加具體 – shayan