在 GitHub 上編輯此頁面

實驗性定義

@experimental 註解允許定義未保證向後二進制或來源相容性的 API。此註解可以放置在術語或類型定義上。

實驗性定義的參考

實驗性定義只能在實驗性範圍內參考。實驗性範圍定義如下

  1. 實驗性 defvalvargiventype 的 RHS 是實驗性範圍。範例

    Example 1
    import scala.annotation.experimental
    
    @experimental
    def x = ()
    
    def d1 = x // error: value x is marked @experimental and therefore ...
    @experimental def d2 = x
    
    val v1 = x // error: value x is marked @experimental and therefore ...
    @experimental val v2 = x
    
    var vr1 = x // error: value x is marked @experimental and therefore ...
    @experimental var vr2 = x
    
    lazy val lv1 = x // error: value x is marked @experimental and therefore ...
    @experimental lazy val lv2 = x
    
    Example 2
    import scala.annotation.experimental
    
    @experimental
    val x = ()
    
    @experimental
    def f() = ()
    
    @experimental
    object X:
      def fx() = 1
    
    def test1: Unit =
      f() // error: def f is marked @experimental and therefore ...
      x // error: value x is marked @experimental and therefore ...
      X.fx() // error: object X is marked @experimental and therefore ...
      import X.fx
      fx() // error: object X is marked @experimental and therefore ...
    
    @experimental
    def test2: Unit =
      // references to f, x and X are ok because `test2` is experimental
      f()
      x
      X.fx()
      import X.fx
      fx()
    
    Example 3
    import scala.annotation.experimental
    
    @experimental type E
    
    type A = E // error type E is marked @experimental and therefore ...
    @experimental type B = E
    
    Example 4
    import scala.annotation.experimental
    
    @experimental class A
    @experimental type X
    @experimental type Y = Int
    @experimental opaque type Z = Int
    
    def test: Unit =
      new A // error: class A is marked @experimental and therefore ...
      val i0: A = ??? // error: class A is marked @experimental and therefore ...
      val i1: X = ??? // error: type X is marked @experimental and therefore ...
      val i2: Y = ??? // error: type Y is marked @experimental and therefore ...
      val i2: Z = ??? // error: type Y is marked @experimental and therefore ...
      ()
    
    Example 5
    @experimental
    trait ExpSAM {
      def foo(x: Int): Int
    }
    def bar(f: ExpSAM): Unit = {} // error: error form rule 2
    
    def test: Unit =
      bar(x => x) // error: reference to experimental SAM
      ()
    
  2. 實驗性 defvalvargiventype 的簽章,或 classtrait 的建構函式是實驗性範圍。範例

    範例 1
    import scala.annotation.experimental
    
    @experimental def x = 2
    @experimental class A
    @experimental type X
    @experimental type Y = Int
    @experimental opaque type Z = Int
    
    def test1(
      p1: A, // error: class A is marked @experimental and therefore ...
      p2: List[A], // error: class A is marked @experimental and therefore ...
      p3: X, // error: type X is marked @experimental and therefore ...
      p4: Y, // error: type Y is marked @experimental and therefore ...
      p5: Z, // error: type Z is marked @experimental and therefore ...
      p6: Any = x // error: def x is marked @experimental and therefore ...
    ): A = ??? // error: class A is marked @experimental and therefore ...
    
    @experimental def test2(
      p1: A,
      p2: List[A],
      p3: X,
      p4: Y,
      p5: Z,
      p6: Any = x
    ): A = ???
    
    class Test1(
      p1: A, // error
      p2: List[A], // error
      p3: X, // error
      p4: Y, // error
      p5: Z, // error
      p6: Any = x // error
    ) {}
    
    @experimental class Test2(
      p1: A,
      p2: List[A],
      p3: X,
      p4: Y,
      p5: Z,
      p6: Any = x
    ) {}
    
    trait Test1(
      p1: A, // error
      p2: List[A], // error
      p3: X, // error
      p4: Y, // error
      p5: Z, // error
      p6: Any = x // error
    ) {}
    
    @experimental trait Test2(
      p1: A,
      p2: List[A],
      p3: X,
      p4: Y,
      p5: Z,
      p6: Any = x
    ) {}
    
  3. 實驗性 classtraitobjectextends 子句是實驗性範圍。範例

    範例 1
    import scala.annotation.experimental
    
    @experimental def x = 2
    
    @experimental class A1(x: Any)
    class A2(x: Any)
    
    
    @experimental class B1 extends A1(1)
    class B2 extends A1(1) // error: class A1 is marked @experimental and therefore marked @experimental and therefore ...
    
    @experimental class C1 extends A2(x)
    class C2 extends A2(x) // error def x is marked @experimental and therefore
    
  4. 實驗性 classtraitobject 的主體是實驗性範圍。範例

    範例 1
    import scala.annotation.experimental
    
    @experimental def x = 2
    
    @experimental class A {
      def f = x // ok because A is experimental
    }
    
    @experimental class B {
      def f = x // ok because A is experimental
    }
    
    @experimental object C {
      def f = x // ok because A is experimental
    }
    
    @experimental class D {
      def f = {
        object B {
          x // ok because A is experimental
        }
      }
    }
    
  5. 實驗性定義的註解在實驗性範圍內。範例

    範例 1
    import scala.annotation.experimental
    
    @experimental class myExperimentalAnnot extends scala.annotation.Annotation
    
    @myExperimentalAnnot // error
    def test: Unit = ()
    
    @experimental
    @myExperimentalAnnot
    def test: Unit = ()
    
  6. 使用 NightlySnapshot 版本編譯器編譯的任何程式碼都被視為處於實驗範圍內。可以使用 -Yno-experimental 編譯器標記來停用它並作為適當的版本執行。

在任何其他情況下,對實驗定義的參照將導致編譯錯誤。

實驗覆寫

對於覆寫成員 M 和被覆寫成員 O,如果 O 是非實驗性的,則 M 必須是非實驗性的。

這確保我們不會有意外的二進位不相容性,例如以下變更。

class A:
  def f: Any = 1
class B extends A:
-  @experimental def f: Int = 2

測試框架

測試可以定義為實驗性的。測試框架可以使用反射來執行測試,即使它們在實驗類、物件或方法中。範例

範例 1

可以如下撰寫觸及實驗 API 的測試

import scala.annotation.experimental

@experimental def x = 2

class MyTests {
  /*@Test*/ def test1 = x // error
  @experimental /*@Test*/ def test2 = x
}

@experimental
class MyExperimentalTests {
  /*@Test*/ def test1 = x
  /*@Test*/ def test2 = x
}

-experimental 編譯器標記

此標記啟用專案中任何實驗語言功能的使用。它透過將 @experimental 註解新增到所有頂層定義來執行此操作。因此,依賴專案也必須是實驗性的。