Я хочу создать сопутствующий объект, который является подклассом параметризованного базового класса, а только фиксирует параметр базовых классов, то есть все методы наследуются от базового класса.
Один из способов сделать это - использовать черту:
class Foo(v: Int, printStream: PrintStream) {
def print: Unit = printStream.println(v);
}
trait FooFactory {
protected val printsTo: PrintStream
def apply(v: Int) = new Foo(v, printsTo)
def makeFoo(v: Int) = apply(v)
}
object Foo extends FooFactory {
protected val printsTo: PrintStream = System.out
}
val foo = Foo(3)
foo.print
val f2 = Foo.makeFoo(2)
f2.print
Этот способ выглядит чище, но Intellij считает, что методы базового класса недоступны вне модуля компиляции (файл .scala, который определяет компаньон):
class Bar(v: Int, printStream: PrintStream) {
def print: Unit = printStream.println(v);
}
class BarFactory(printsTo: PrintStream) {
def apply(v: Int) = new Bar(v, printsTo)
def makeBar(v: Int) = apply(v)
}
object Bar extends BarFactory(System.out) {}
val bar = Bar(3)
bar.print
val b2 = Bar.makeBar(2)
b2.print
Эффективно ли они эквивалентны (за исключением, конечно, смены имени Foo => Bar)? Один предпочтительнее?
Цель состоит в том, чтобы предоставить сопутствующему объекту PrintStream по умолчанию, позволяя при этом пользователям создавать другие фабрики, если им необходимо:
val BarLoggerFactory = new BarFactory(someLogPrintStream)
val bar3 = BarLoggerFactory.makeBar(3);