简体   繁体   中英

Dependent types not working for constructors?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM