此頁面中描述的兩個不相容性是類型推論規則中的故意變更。
其他不相容性可能是由類型推論演算法的替換所造成的。新的演算法比舊的演算法更好,但有時它可能會在 Scala 2.13 成功的地方失敗
始終建議明確撰寫所有公開值和方法的結果類型。這可以防止您的函式庫的公開 API 因為不同的推論類型而隨著 Scala 版本而改變。
這可以在 Scala 3 遷移之前透過使用 Scalafix 中的 ExplicitResultTypes 規則來完成。
覆寫方法的傳回類型
在 Scala 3 中,覆寫方法的傳回類型會從基底方法繼承而推論出來,而在 Scala 2.13 中,它會從覆寫方法的左側推論出來。
class Parent {
def foo: Foo = new Foo
}
class Child extends Parent {
override def foo = new RichFoo(super.foo)
}
在此範例中,Child#foo
在 Scala 2.13 中傳回 RichFoo
,但在 Scala 3 中傳回 Foo
。它可能會導致編譯器錯誤,如下所示。
class Foo
class RichFoo(foo: Foo) extends Foo {
def show: String = ""
}
class Parent {
def foo: Foo = new Foo
}
class Child extends Parent {
override def foo = new RichFoo(super.foo)
}
(new Child).foo.show // Scala 3 error: value show is not a member of Foo
在某些罕見的情況下,涉及隱式轉換和執行時期強制轉型,甚至可能導致執行時期失敗。
解決方案是明確指定覆寫方法的傳回類型
class Child extends Parent {
- override def foo = new RichFoo(super.foo)
+ override def foo: RichFoo = new RichFoo(super.foo)
}
反射類型
Scala 2 反射呼叫已捨棄,並由更廣泛的 程式化結構類型 取代。
Scala 3 可透過讓 scala.reflect.Selectable.reflectiveSelectable
可在任何匯入 scala.language.reflectiveCalls
的地方使用,來模仿 Scala 2 反射呼叫。然而,Scala 3 編譯器預設不會推斷結構類型,因此無法編譯
import scala.language.reflectiveCalls
val foo = new {
def bar: Unit = ???
}
foo.bar // Error: value bar is not a member of Object
直接的解決方案是寫下結構類型。
import scala.language.reflectiveCalls
- val foo = new {
+ val foo: { def bar: Unit } = new {
def bar: Unit = ???
}
foo.bar
此頁面的貢獻者
內容
- 相容性參考
- 來源層級
- 類別路徑層級
- 執行時間
- 元程式設計
- 遷移工具巡禮
- 使用 -Xsource:3 的 Scala 2
- Scala 3 遷移模式
- 遷移教學
- 先決條件
- 移植 sbt 專案(使用 sbt-scala3-migrate)
- 移植 sbt 專案(手動)
- 交叉建置巨集程式庫
- 混合 Scala 2.13 和 Scala 3 巨集
- Scala 3 語法重寫
- 不相容性表
- 語法變更
- 已移除功能
- 脈絡抽象
- 其他已變更功能
- 類型檢查器
- 類型推論
- 編譯器選項
- 編譯器選項查詢表
- 新的編譯器選項
- Scala2 和 Scala3 之間的 Scaladoc 設定相容性
- 編譯器外掛程式
- Kind Projector 遷移
- 外部資源