Path-dependent types are useful:
trait Sys {
type Global
}
def foo[S <: Sys](system: S)(global: system.Global) = ()
Why doesn't this work for constructors?
class Foo[S <: Sys](val system: S)(val global: system.Global)
Or am I just doing it wrong?
This seems like a bug to me. Edit: found it, this is SI-5712.
Section §5.3 of the 2.9 SLS says:
(ps1 ) . . . (psn ) are formal value parameter clauses for the primary constructor of the class. The scope of a formal value parameter includes all subsequent parameter sections and the template t .
There is an exception:
However, a formal value parameter may not form part of the types of any of the parent classes or members of the class template t .
But it says it cannot be part of the types of any of the parent classes or members, not of any of the following parameter sections, so it does not seems to forbid path-dependent types between argument groups.
You can go around this with a secondary constructor:
class Foo[S <: Sys] private[this] () {
def this(system: S)(global: system.Global) = this
}
Edit: this secondary constructor workaround is not very good: exposing system
or global
become very difficult because only the primary constructor can declare val
s.
An example with a cast:
class Foo[S <: Sys] private[this] () {
private[this] var _system: S = _
private[this] var _global: system.Global = _
def this(system0: S)(global0: system0.Global) = {
this
_system = system0
_global = global0.asInstanceOf[system.Global]
}
lazy val global: system.Global = _global
lazy val system: S = _system
}
But this is getting awful. @senia's suggestion is much better.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With