I may be having a silly problem here... I can't seem to figure out how to make a constructor without parameters in Scala. I know I can just write the whole thing in the class body (especially because it's the only constructor I need), but it doesn't quite feel right.
What I have:
class Foo {
//some init code
//...
}
What I'd like (but doesn't work as it wants me to call another constructor first):
class Foo {
// The only constructor
def this() = {
//some init code
}
//...
}
All classes in Scala have a primary constructor and optionally some auxiliary constructors (which must defer to the primary constructor or another auxiliary constructor).
The issue in your case is that in both cases you've defined the primary constructor as taking no arguments - and then in the second case you try to define an auxiliary constructor with the same signature. This doesn't work, for the same reason that the following wouldn't compile:
// Primary constructor takes a String
class Foo(s: String) {
// Auxiliary constructor also takes a String?? (compile error)
def this(a: String) {
this(a)
}
}
This isn't anything to do with the fact that the constructor is no-args; the following compiles for example:
class Foo(s: String) {
// alternative no-arg constructor (with different signature from primary)
def this() {
this("Default value from auxiliary constructor")
}
}
In particular, in your second example, your comment "the only constructor" is wrong. Auxiliary constructors are always secondary to the primary constructor, and cannot ever be the only constructor.
FWIW, the first example is the only option open to you, but it looks fine to me. If you've just started using Scala I'm sure it will start to feel right soon enough - and it's important to eschew Java-esque ways of doing things when there are more idiomatic alternatives.
For what it's worth you can introduce an extra scope to "mark" the init code.
class Foo {
{
// init code here
}
}
Well putting the init code in the class body is the only way to have a constructor without parameters. I suppose if you want you could do something like :
class Foo {
private def init {
//init code here
}
init()
}
that's as close as you're gonna get.
The init code is the body of the method. But you can do this, if it bothers you all that much:
class Foo {
locally {
//some init code
}
}
Related
This question is somewhat hard to summarize. Following code block shows what I want to do.
I have a base class like this:
`class Base {
def methA:String="ook"
def methB:Int=1
}
Also I have a derived class, where I want each subclass method to call the super class method twice, compare the results and throw an exception on mismatch (this is for a test scenario).
But if I write
class Derived extends Base {
private def callDoublyAndCompare[T](fun:()=>T) : T = {
val fst=fun()
val snd=fun()
if(fst!=snd) throw new RuntimeException(s"Mismatch fst=$fst != snd=$snd")
snd
}
override def methB:Int={
callDoublyAndCompare(() => super[Derived].methB)
}
}
Then this will not compile. The only way out of this problem sofar has been to extract a method in class Derived which only calls the superclass' methB and to call this from the lambda call.
Is there a better way?
I understood you want to call super call method. Hope below is what you want.
You can call that as below with the key word super only
(new Derived).methB . This will call super call method in callDoublyAndCompare twice as per your code .
class Derived extends Base {
private def callDoublyAndCompare[T](fun:()=>T) : T = {
val fst=fun()
val snd=fun()
if(fst!=snd) throw new RuntimeException(s"Mismatch fst=$fst != snd=$snd")
snd
}
override def methB:Int={
callDoublyAndCompare(() => super.methB) //kept only super
}
}
The original example was not fully complete insofar as the Derived class was defined as inner class of another scala class.
After I moved out this inner class to the top level, the example from Praveen above suddenly worked.
I have an abstract superclass with a variety of stateless implementations. It seems like the thing to do is make the abstract superclass a class, and make each implementation an object because I only ever need one of each.
This is a toy example, but it shows the compile error I’m getting:
// Tramsformer.scala
class Transformer {
def transform(value : String) : String
}
object Transformer {
getTransformer(String : name) : Transformer = {
name match {
case "upper" => UpperTransformer
// I'm getting "Cannot Resolve Symbol" on UpperTransformer,
// even though they're in the same package.
case _ => throw new IllegalArgumentException("...")
}
}
}
// ---
// UpperTransformer.scala is in the same package
object UpperTransformer extends Transformer {
override def transform(vlaue : String) = foo.toUpperCase()
}
I’m really shooting for some sort of dynamic dispatch on (dataProvider, desiredAction) here.
Then some class can call Transformer.getTransformer("upper").transform("stack-overflow") without making any unnecessary objects.
Any idea what I should be doing differently? Should I stop worrying about premature optimization and learn to love the instance?
The problem isn't visibility, it's that you simply do not define an object named UpperTransformer anywhere - only a class. If you replace class UpperTransformer with object UpperTransformer, your code should work fine.
The code below gives a compile error:
class Info(val x: String)
object Info {
val default = new Info("top")
}
case class Data(x: String) {
import Info.default
def this() = this(default.x)
}
Error:(11, 23) not found: value default
def this() = this(default.x)
Why is symbol default not seen in the constructor, in spite of the import?
Further experiments show it is not only import. Replacing import line with a def (or even val) does not help, still the error persists:
def default = Info.default
Scoping doesn't work the way you expected because of the scoping of self constructor invocations (when secondary constructors invoke the primary constructor):
The signature and the self constructor invocation of a constructor
definition are type-checked and evaluated in the scope which is in
effect at the point of the enclosing class definition, augmented by
any type parameters of the enclosing class and by any early
definitions of the enclosing template.
In other words, the scope in effect for the expression default.x is the scope outside Data.
This is confusing because textually it looks like that expression is inside the class.
This rule has to do with lexical scope and not with evaluation order.
You have to move the import outside the class definition.
For fun, scoping is slightly broken in the following case:
object Playroom {
def default = "playing"
case class Toy(squeezeMsg: String = default)
object Toy {
def default = "srsly"
}
}
object Test extends App {
import Playroom._
println(Toy())
println(new Toy())
}
which is this puzzler. Generally speaking, it's more idiomatic (and robust) to use apply methods on the companion.
This is behaving according to specs. The body of the class is part of the so called primary constructor. The auxiliary constructor(s) needs to start by calling the primary or another auxiliary defined before. Assuming you only have one auxiliary, since the call to primary must be the first statement in your auxiliary, it means that during this first statement you do not have access to anything defined inside the primary. After the first call is done, then you can access any of the members and imports defined in the primary.
In your example, the problem is that the import (import Info.default) is not visible to the first statement of your auxiliary. If you replace it with def this() = this(Info.default.x) it should work.
Example:
The following compiles fine since the call to Constant is done after the call to the primary.
class G(i: Int) {
val Constant = 1
// No argument auxiliary constructor
def this() = {
this(3) // Call to primary
println(Constant * 2)
}
}
The following does not compile since the call to Constant is done before the call to the primary, which means that Constant has not been created yet.
class G(i: Int) {
val Constant = 1
// No argument auxiliary constructor
def this() = {
this(Constant) // This will cause an error!
}
}
Solution:
Have any constants you need defined in the companion object. The companion object is by definition initialized first, so you will be able to access any members of it from within the constructors of your class.
object G {
val Constant = 1
}
class G(i: Int) {
// No argument auxiliary constructor
def this() = {
this(G.Constant) // This now works!
}
}
In scala, any fields defined in the class is not available until after the primary constructor is invoked. To fix it is usually used companion object with apply method.
I'm learning Scala. I want to implement a subclass of Exception that gets a name as parameter and builds a message with that name embedded on it. Something similar to this:
class InvalidItem(itemName: String) extends Exception(msg: name) {
def this(itemName)= {
super("Invalid item: " + itemName)
}
}
In this case, I simply want to prepend itemName with "Invalid item:" before passing it to the superconstructor. But I can't find the way.
I've tried several similar syntaxes (i.e. replacing super by this) but kept getting cryptic errors.
What is the correct way of doing this in Scala?
You're actually calling the parent constructor in the extends clause, so the following works:
class InvalidItem(itemName: String) extends Exception("Invalid item name" + itemName)
For a discussion of this syntax and its motivation, see for example this blog post by Daniel Spiewak:
That little bit of extra syntax in the extends clause is how you
call to a superclass constructor... This may seem just a bit odd at
first glance, but actually provides a nice syntactical way to ensure
that the call to the super constructor is always the first statement
in the constructor. In Java, this is of course compile-checked, but
there’s nothing intuitively obvious in the syntax preventing you
from calling to the super constructor farther down in the
implementation. In Scala, calling the super constructor and calling a
superclass method implementation are totally different operations,
syntactically. This leads to a more intuitive flow in understanding
why one can be invoked arbitrarily and the other must be called prior
to anything else.
class InvalidItem private(val name: String) extends Exception(name)
object InvalidItem{
def apply(name: String) = new InvalidItem("Invalid item: " + name)
}
object Text extends App{
val item = InvalidItem("asd")
println(item.name)
//Invalid item: asd
}
I know that objects are treated pretty much like singletons in scala. However, I have been unable to find an elegant way to specify default behavior on initial instantiation. I can accomplish this by just putting code into the body of the object declaration but this seems overly hacky. Using an apply doesn't really work because it can be called multiple times and doesn't really make sense for this use case.
Any ideas on how to do this?
Classes and objects both run the code in their body upon instantiation, by design. Why is this "hacky"? It's how the language is supposed to work. If you like extra braces, you can always use them (and they'll keep local variables from being preserved and world-viewable).
object Initialized {
// Initalization block
{
val someStrings = List("A","Be","Sea")
someStrings.filter(_.contains('e')).foreach(s => println("Contains e: " + s))
}
def doSomething { println("I was initialized before you saw this.") }
}
scala> Initialized.doSomething
Contains e: Be
Contains e: Sea
I was initialized before you saw this.
scala> Initialized.someStrings
<console>:9: error: value someStrings is not a member of object Initialized
Initialized.someStrings
Rex has it right, I just wanted to point out a pattern I use a lot, that saves you from having to use vars, while avoiding namespace pollution by intermediate values.
object Foo {
val somethingFooNeeds = {
val intermediate = expensiveCalculation
val something = transform(intermediate)
something
}
}
If it makes you feel better, you can create some class with protected constructor and object will create singleton of this class:
sealed class MyClass protected (val a: String, b: Int) {
def doStuff = a + b
}
object MyObject extends MyClass("Hello", b = 1)
Also notice, that sealed stops other classes and objects to extend MyClass and protected will not allow creation of other MyClass instances.
But I personally don't see any problems with some code in the body of the object. You can also create some method like init and just call it:
object MyObject {
init()
def init() {
...
}
}
The body of object and class declarations IS the default constructor and any code placed in there will be executed upon first reference, so that is exactly the way to do it.