Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference a constructor argument from a trait

In Scala, is it possible for a trait to reference a named constructor argument of the class it is mixed into? The code below doesn't compile because ModuleDao's constructor argument is not a val as defined in the trait. If I add val before the constructor argument to make it public, it matches up with the one in the trait and it compiles, but I'd prefer not to set it as a val.

trait Daoisms {
  val sessionFactory:SessionFactory
  protected def session = sessionFactory.getCurrentSession
}

class ModuleDao(sessionFactory:SessionFactory) extends Daoisms {
  def save(module:Module) = session.saveOrUpdate(module)
}

/* Compiler error:
class ModuleDao needs to be abstract, since value sessionFactory in trait Daoisms of type org.hibernate.SessionFactory is not defined */

// This works though
// class ModuleDao(val sessionFactory:SessionFactory) extends Daoisms { ... }
like image 202
Nick Avatar asked Oct 10 '11 12:10

Nick


People also ask

Can we use constructor in trait?

Unlike traits in Scala, traits in PHP can have a constructor but it must be declared public (an error will be thrown if is private or protected). Anyway, be cautious when using constructors in traits, though, because it may lead to unintended collisions in the composing classes.

Can a Scala trait take parameters?

Scala 3 allows traits to have parameters, just like classes have parameters. Arguments to a trait are evaluated immediately before the trait is initialized.

Can traits have constructors Scala?

Traits does not contain constructor parameters. When a class inherits one trait, then use extends keyword.

Can a trait extend a class Scala?

Yes they can, a trait that extends a class puts a restriction on what classes can extend that trait - namely, all classes that mix-in that trait must extend that class .


1 Answers

If your only concern with making it a val is visibility, you can just make the val protected like so:

scala> trait D { protected val d:Int
     | def dd = d
     | }
defined trait D

scala> class C(protected val d:Int) extends D
defined class C

scala> new C(1)
res0: C = C@ba2e48

scala> res0.d
<console>:11: error: value d in class C cannot be accessed in C
 Access to protected value d not permitted because
 enclosing class object $iw in object $iw is not a subclass of 
 class C in object $iw where target is defined
              res0.d
                   ^

scala> res0.dd
res2: Int = 1
like image 124
Kim Stebel Avatar answered Oct 10 '22 05:10

Kim Stebel