Scala - mixing in a trait with its imports (inheriting imports) - scala

I have the following code:
trait A {
import org.somepackage.C._
}
class B extends A {
def getValue = value
^^^^^
}
object C {
var value = 5
}
The value in class B is not visible what means that the inherent import of class A was not inherited by B, although the value is perfectly visible inside A. How to achieve the effect of also inheriting imports so I could avoid explicitly importing same things in multiple classes where trait A mixes in?

Imports not being a first class entity do not exhibit the behavior you are expecting. You can instead restructure your design thusly to achieve something close:
trait A with C {
}
class B extends A {
def getValue = value // Now this will work.
}
trait C {
var value = 5
}
object C extends C
This idiom is used in Scalaz 6 to tax users with as few imports as possible.

Related

Reassignment to val error when var member of base class in scala

Scala throws "reassignment to val" error for the following code.
abstract case class Gun(var bulletCount:Int)
class Pistol(bulletCount:Int) extends Gun(bulletCount){
def fire() { bulletCount=bulletCount-1 }
}
Anything I missed here?
For starters, you should consider case class as final, and not extend them.
Second, do not use var with case class, you should rather create a copy of a case class to get one of its field changed.
Third, if you want a common type, you can use a base trait.
All in one, here's what it could look like:
sealed trait Gun {
def bulletCount: Int
}
case class Pistol(bulletCount: Int) extends Gun {
def fire(): Pistol = copy(bulletCount=bulletCount)
}
You're referring to bulletCount field generated by Pistol primary constructor parameter. To set base class variable, you need to directly call field using super:
class Pistol(bulletCount: Int) extends Gun(bulletCount) {
def fire(): Unit = {
super.bulletCount = super.bulletCount - 1
}
}
Alternatively, you can label parameter-generated field with override var:
class Pistol(override var bulletCount: Int) extends Gun(bulletCount) {
def fire(): Unit = {
bulletCount = bulletCount - 1
}
}
On a side note, as Frederic A. suggested in his answer, you should avoid inheriting case classes. They are syntactic sugar, and code generation don't work over inheritance - you'll need to implement all the fancy stuff like apply or unapply methods in companion class all by yourself. Scala compiler team tried to support case class to case class inheritance, but discovered that it breaks structural equality and lots of other things.

scala: how to wrap execution of subclass constructor?

in scala, i have a base class and a number of child classes. without adding code to a child class or changing the instantiation of a child class, i would like the base class to be able to call some code both before and after the child constructor is executed. before is easy since the base class constructor is called before the child's, but i don't see a way to handle the after case. as a bit of example code:
class A {
// do some stuff before child constructor is called
// ...
// do some other stuff after child constructor is called
// this could be a method or inline in the constructor, doesn't matter.
}
class B extends A { // stuff happens in between }
class C extends A { // stuff happens in between }
etc
val b = new B // everything happens inside, no other method call needed
is this behavior possible? thanks.
If you use Scala 2.9, you can arrange something like this:
class A {
println("Hi")
}
class B extends A with DelayedInit {
private[this] var count = 0
println("Hey")
def delayedInit(x: => Unit) {
x
count += 1
if (count==2) { println("There") }
}
}
class C extends B { println("Ho") }
class D extends C { println("Ha") }
This takes advantage of the new DelayedInit trait which sends delayed constructors from the current and all child classes to a delayedInit method. Unfortunately, since there is not a termination signal, you're limited to skipping a single constructor. So for C, we get:
scala> new C
Hi
Hey
Ho
There
where the "There" block has magically appeared after the "Ho" block from C. Unfortunately if you extend C, the new initialization happens last:
scala> new D
Hi
Hey
Ho
There
Ha
(You don't really need A there...I just put it there to illustrate what happens with superclasses.)
An 'end of concrete class' callback is possible,
the code below outputs :
hello
world1
world2
world3
end of the worlds !
trait A extends DelayedInit {
def delayedInit(body: => Unit) = {
body
println("end of the worlds !")
}
}
trait B extends A { println("hello") }
trait C extends B { println("world1") }
trait D extends C { println("world2") }
object Zozo extends D {
println("world3")
}

Seamless weaving of trait

I would like to automatically weave the definition of a new function say introduced by an extending trait Ext into an abstract class A:
class Base {
abstract class A
class B extends A
case class C extends A
}
trait Ext extends Base {
trait A extends super.A {
def say = "hello"
}
}
object Test extends Base with Ext {
val b = new B
b.say
}
However, I obtain the following error:
<console>:12: error: value say is not a member of Test.B
b.say
Any way of doing it?
It seems you are trying to use virtual classes, which is a feature not available in Scala.
Once A and B are defined they can't be redefined (like method overriding).
abstract class A
class B extends A
On the other hand, given your example, your objective could be achieved by a simple mixin. Here it is with few rewrites:
class Base {
abstract class A
class B extends A
case class C extends A
}
trait Ext extends Base {
trait CanSay extends A {
def say = "hello"
}
}
object Test extends Base with Ext {
val b = new B with CanSay
def apply = b.say
}
Test.apply
No sure it will really help, but at least will help you understand what is going on.
Okay, as I said in a comment, it's not entirely clear what you're trying to do here, so I can't really try to suggest ways to do it. However, the approach you're using at the moment will not work.
Consider the class Hierarchy in this situation. At the base, we have A, which is then subclassed with B (in Base) and with Ext.A. These are not related save by their shared supertype, so you'll never find a say method on an instance of B.
The confusion possibly arises through the use of the word abstract. An abstract modifier on a class (even an inner class) does not make it an abstract member of the parent class, but denotes that it itself may have abstract members. There are ways of giving a class an abstract class member - through type parameters or type members. Unfortunately, you cannot derive from these AFAIK.

Scala protected object

In Scala, if I create an object and companion class, identifiers declared with the protected modifier can be accessed from the class if the object is imported:
object Foo {
protected val X = 42
}
class Foo {
import Foo._
def getX(): Int = X
}
However, the protected identifier cannot be accessed from a subclass of the class Foo:
class Bar extends Foo {
import Foo._
def getX(): Int = X * 2
}
I get a compile-time error in Bar.
Other then (implied) public, is there any access modifier I can place on X so that it can be accessed from subclasses of its companion, but not from other classes, including other classes in the same package?
That's because only the class Foo is companion to the object Foo.
Here, the difference between private and protected meaningless, since the object Foo is a singleton, which means there isn't any other object that has the same class as object Foo (Foo.type).
Access restriction in Scala is package-based, so the short answer is no. You could make a forwarder on the base class, though, unless you need it to be available without an instance.
In your place, however, I'd go back to the design board.
In such cases, I would suggest using a package private modifier, like below:
object Foo {
private[your_package] val X = 42
}
The value will still be visible to everybody else in the package.
To achieve the same thing, One solution to this problem can be:
class Bar extends Foo {
import Foo._
override def getX(): Int = super.getX * 2
}

scala: mixins depending on type of arguments

I have a set of classes of models, and a set of algorithms that can be run on the models. Not all classes of models can perform all algorithms. I want model classes to be able to declare what algorithms they can perform. The algorithms a model can perform may depend on its arguments.
Example: Say I have two algorithms, MCMC, and Importance, represented as traits:
trait MCMC extends Model {
def propose...
}
trait Importance extends Model {
def forward...
}
I have a model class Normal, which takes a mean argument, which is itself a Model. Now, if mean implements MCMC, I want Normal to implement MCMC, and if mean implements Importance, I want Normal to implement Importance.
I can write:
class Normal(mean: Model) extends Model {
// some common stuff goes here
}
class NormalMCMC(mean: MCMC) extends Normal(mean) with MCMC {
def propose...implementation goes here
}
class NormalImportance(mean: Importance) extends Normal(mean) with Importance {
def forward...implementation goes here
}
I can create factory methods that make sure the right kind of Normal gets created with a given mean. But the obvious question is, what if mean implements both MCMC and Importance? Then I want Normal to implement both of them too. But I don't want to create a new class that reimplements propose and forward. If NormalMCMC and NormalImportance didn't take arguments, I could make them traits and mix them in. But here I want the mixing in to depend on the type of the argument. Is there a good solution?
Using self types allows you to separate the Model-Algorithm implementations from the instantiations and mix them in:
trait Model
trait Result
trait MCMC extends Model {
def propose: Result
}
trait Importance extends Model {
def forward: Result
}
class Normal(val model: Model) extends Model
trait NormalMCMCImpl extends MCMC {
self: Normal =>
def propose: Result = { //... impl
val x = self.model // lookie here... I can use vals from Normal
}
}
trait NormalImportanceImpl extends Importance {
self: Normal =>
def forward: Result = { // ... impl
...
}
}
class NormalMCMC(mean: Model) extends Normal(mean)
with NormalMCMCImpl
class NormalImportance(mean: Model) extends Normal(mean)
with NormalImportanceImpl
class NormalImportanceMCMC(mean: Model) extends Normal(mean)
with NormalMCMCImpl
with NormalImportanceImpl
Thanks to Kevin, Mitch, and Naftoli Gugenheim and Daniel Sobral on the scale-users mailing list, I have a good answer. The two previous answers work, but lead to an exponential blowup in the number of traits, classes and constructors. However, using implicits and view bounds avoids this problem. The steps of the solution are:
1) Give Normal a type parameter representing the type of its argument.
2) Define implicits that take a Normal with the right type of argument to one that implements the appropriate algorithm. For example, makeImportance takes a Normal[Importance] and produces a NormalImportance.
3) The implicits need to be given a type bound. The reason is that without the type bound, if you try to pass a Normal[T] to makeImportance where T is a subtype of Importance, it will not work because Normal[T] is not a subtype of Normal[Importance] because Normal is not covariant.
4) These type bounds need to be view bounds to allow the implicits to chain.
Here's the full solution:
class Model
trait Importance extends Model {
def forward: Int
}
trait MCMC extends Model {
def propose: String
}
class Normal[T <% Model](val arg: T) extends Model
class NormalImportance(arg: Importance) extends Normal(arg) with Importance {
def forward = arg.forward + 1
}
class NormalMCMC(arg: MCMC) extends Normal(arg) with MCMC {
def propose = arg.propose + "N"
}
object Normal {
def apply[T <% Model](a: T) = new Normal[T](a)
}
object Importance {
implicit def makeImportance[T <% Importance](n: Normal[T]): Importance =
new NormalImportance(n.arg)
}
object MCMC {
implicit def makeMCMC[T <% MCMC](n: Normal[T]): MCMC = new NormalMCMC(n.arg)
}
object Uniform extends Model with Importance with MCMC {
def forward = 4
def propose = "Uniform"
}
def main(args: Array[String]) {
val n = Normal(Normal(Uniform))
println(n.forward)
println(n.propose)
}
Much of your problem seems to be that NormalMCMC and NormalImportance take arguments but, as you correctly imply, traits can't have constructors.
Instead, you can take the parameters that you'd want to supply via a trait constructor (if such a thing existed) and make them abstract members of the trait.
The members then get realised when the trait is constructed.
Given:
trait Foo {
val x : String //abstract
}
you can use it as either of the following:
new Bar with Foo { val x = "Hello World" }
new Bar { val x = "Hello World" } with Foo
Which gives you back the equivalent functionality of using Trait constructors.
Note that if the type Bar already has a non-abstract val x : String then you can simply use
new Bar with Foo
In some scenarios it can also help to make x lazy, which can gives you more flexibility if initialization order should become an issue.