私は、初期化が本質的にスレッドセーフではないという特性を持っていますが、定義により初期化がスレッドセーフ であるコンパニオンオブジェクトのベースとして使用することを厳密に意図しています。
特性が常にコンパニオン オブジェクトによって拡張されることを (コンパイル時または実行時に) 保証する方法はありますか? トレイトには、コンパニオン オブジェクトの初期化中にのみ呼び出されるメソッドがあり、検証のサイトになる可能性があります。
私は、初期化が本質的にスレッドセーフではないという特性を持っていますが、定義により初期化がスレッドセーフ であるコンパニオンオブジェクトのベースとして使用することを厳密に意図しています。
特性が常にコンパニオン オブジェクトによって拡張されることを (コンパイル時または実行時に) 保証する方法はありますか? トレイトには、コンパニオン オブジェクトの初期化中にのみ呼び出されるメソッドがあり、検証のサイトになる可能性があります。
次の解決策は、子クラスのコンストラクターの数をチェックします。これは、クラスには少なくとも 1 つのコンストラクターがあるのに対し、オブジェクトには 0 つのコンストラクターがあるという観察に基づいています。
チェックは実行時に行われます。
trait Y {
// objects have 0 constructors, everything else has >= 1 constructors
require(getClass.getConstructors.length == 0, "Trait Y should be extended by objects only")
def hello(): Unit
}
class Foo$ extends Y {
def hello() = println("Hello Foo$")
}
class Foo extends Y {
def hello() = println("Hello Foo")
}
object Bar extends Y {
def hello() = println("Hello Bar")
}
object Test extends App {
new Foo().hello() // exception is thrown
new Foo$().hello() // exception is thrown
Bar.hello() // prints Hello Bar
}