簡體   English   中英

Scala:約束成員函數的類類型參數

[英]Scala: constrain a class type parameter for a member function

給定具有類型參數T A類,我如何進一步限制T的特定功能? 在下面的示例中,我想強制執行以下操作:僅當TInt (或子類型,如果您願意)時,才能調用foo 即,應該編譯new A[Int]().foo() ,但不應編譯new A[Double]().foo()

我可以通過隱式轉換T => Int實現我想要的結果,如foo 但是,這會導致不必要的方法調用-隱式找到的證據是身份函數。 而且,它看起來也不是很好...

class A[T] {
  val someValue: T = ???

  def foo()(implicit ev: T => Int): Int = ev(someValue)

  // some ideas that don't quite work
  // def bar[T2 <: Int :EqualTo[T]](t2: T2): T = t2.asInstanceOf[T]
  // def bam[T2 <: T with Int](): Int = someValue.asInstanceOf[Int]

  def thisOneDefinesItsOwnConstraintType[Z <: Int](z: Z): Z = z
  def thisOneDoesNotNeedToConstrainT(t: T): T = someValue
}

如果不需要強制轉換,該解決方案將獲得加分:)

注意:我知道我可以在類或方法級別上定義類型約束(請參見thisOneDefinesItsOwnConstraintType ),但這thisOneDefinesItsOwnConstraintType ,因為我還有一些不需要約束類型的方法(請參見thisOneDoesNotNeedToConstrainT )。

我看不到沒有隱式方法的方法,因為雖然您可以在類方法上施加一些約束B <: C ,但是您對B <: T要求很難概括,因為我們不知道C如何與任意T 幸運的是,Scala已經為此構造了<:<類型類。 Predef生成的<:<[B, T]Predef將提供B <: C證據。

但是,不要只聽我的話,這就是斯卡拉多醫生必須說的:

要限制方法參數列表中范圍內的任何抽象類型T(而不僅僅是方法自身的類型參數),只需添加類型T <:<U的隱式參數,其中U是所需的上限; 或對於下限,請使用:L <:<T,其中L是所需的下限。

例如:

class E
class F extends E
class G extends F

class A[T] {
  def constrained[B <: F](b: B)(implicit ev: B <:< T): B = b
}

在這里,我們引入一個上界的F類型參數B所述的contrained方法。 但是,如果你想保證B <: T (無需添加其他類型的參數),您可以添加隱B <:< T

scala> val a = new A[E]
a: A[E] = A@5a63f509

scala> a.constrained(new E)
<console>:15: error: inferred type arguments [E] do not conform to method constrained's type parameter bounds [B <: F]
       a.constrained(new E)
         ^
<console>:15: error: type mismatch;
 found   : E
 required: B
       a.constrained(new E)
                     ^

scala> a.constrained(new F)
res5: F = F@4a668b6e

scala> a.constrained(new G)
res6: G = G@4de4b452

怎么樣:

implicit class AIntOps(a: A[Int]) {
  def test(x: Int) = x
}

使用該方法,測試僅對A[Int]出現,而對其他任何A都不可用

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM