我試圖在 Scala 中創建一個可以處理所有 Integer 型別的通用計算器。當我嘗試以下代碼時,它給了我一個錯誤
錯誤:“型別不匹配。必需:字串,找到:T”
class Calculator[T <: Integral[T]] {
def add[T](a: T, b: T): T = a a
}
有人可以向我解釋一下它是如何期待 String 型別的嗎?
uj5u.com熱心網友回復:
要回答具體問題,型別a b是String因為 Scala 有一個默認值,通過將兩個引數都轉換為 a并將它們連接起來 ,它適用于任何物件。String但這就是說,沒有其他方法可以使用 。a
更廣泛的問題是它Numeric不是所有數字型別的基類,而是定義型別上的數字行為的型別類T。所以類定義應該是這樣的:
class Calculator[T : Integral] {
這告訴編譯器你不能創建一個實體,Calculator[T]除非當時Integral[T]編譯器有一個可見的隱式實體。
所以有一個實體,Integral[T]它有一些方法可以進行T基本的數字運算(plus、times等negate)。下一個問題是,我如何獲得這個實體Integral[T]?答案是implicitly,只要型別可用,它將回傳型別的型別值(否則它是編譯時錯誤)。
因此,該運算式implicitly[Integral[T]]將回傳Integral[T]用于創建Calculator. 并且該實體知道如何獲取plustype 的值T。一旦你知道了這一點,你就可以撰寫你的add函式:
class Calculator[T : Integral] {
def add(a: T, b: T): T = implicitly[Integral[T]].plus(a, b)
}
[還要注意沒有型別引數 onadd因為型別引數在類上,所以它不是def add[T](...)而只是def add(...)]
uj5u.com熱心網友回復:
你看到的原因
Error: "Type mismatch. Required: String, found: T"
是默認情況下Scala 2定義了以下隱式方法 Predef
implicit final class any2stringadd[A](private val self: A) extends AnyVal {
def (other: String): String = String.valueOf(self) other
}
(這不會在 Scala 3 中編譯)。如果您想撰寫適用于所有整數型別的單個非泛型計算器類(無論這對您意味著什么 - Scala 沒有將型別限制為僅Int, Byte,的繼承層次結構Long)。您將使用自己的Integer型別類
class Calculator {
def add[A: Integer](lhs: A, rhs: A): A = implicitly[Integer[A]].plus(lhs, rhs)
}
具有以下定義
trait Integer[A] {
def plus(lhs: A, rhs: A): A
}
object Integer {
implicit val Int: Integer[Int] = new Integer[Int] {
override def plus(lhs: Int, rhs: Int): Int = lhs rhs
}
// note explicit toByte cast -> byte addition can overflow!
// (thus result type is Int and you might want to stick
// to the original type in your use case)
implicit val Byte: Integer[Byte] = new Integer[Byte] {
override def plus(lhs: Byte, rhs: Byte): Byte = (lhs rhs).toByte
}
}
為了讓它看起來更好一點,您可以利用擴展方法。
class Calculator {
import Integer._
def add[A: Integer](lhs: A, rhs: A): A = lhs rhs
}
object Integer {
implicit class IntegerOps[A: Integer](lhs: A) {
def (rhs: A): A = implicitly[Integer[A]].plus(lhs, rhs)
}
// the rest of the object stays the same
}
使用 Scala 3,您可以更簡潔地撰寫它
class Calculator {
def add[A: Integer](lhs: A, rhs: A): A = lhs rhs
}
trait Integer[A]:
extension(a: A) def (b: A): A
given Integer[Int] with
extension(a: Int) def (b: Int): Int = a b
given Integer[Byte] with
extension(a: Byte) def (b: Byte): Byte = (a b).toByte
編輯:根據@Tim 的建議,您可以使用Integral預定義的型別類。如果您想自己實作類似的型別類,我仍然會留下我的答案作為參考。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/413850.html
標籤:
