I am having a hard time understanding how to get the following code structure to work.
In Scala I have a class MyClass which inherits from SomeClass I added a var member variable in this case called mutableArray and it is being updated in the overridden method overridingSomeClassMethod and is called when I create a new instance of the MyClass a number of times right away. But in main when I try and get the updated mutableArray variable it prints out the instantiated var as if it is immutable or only has scope in the overriding method.
I can't change the method in parent SomeClass, and I tried creating a companion object as well as putting the variable in the encompassing SomeOtherObject but I get the same exact issue.
import scala.collection.mutable.ArrayBuffer
object SomeOtherObject{
case MyClass(...) extends SomeClass(..){
var mutableArray: ArrayBuffer[Int] = ArrayBuffer.fill(5)(0)
def overridingSomeClassMethod(...){
var someReturnVar = 0.0
mutableArray(0) += 1
println(mutableArray.mkString) // last output -> 84169
someReturnVar
}
}
def main(args: Array[String]){
var mc = new MyClass
println(mc.mutableArray.mkString) // output -> 00000
}
}
You can use an early initializer:
case MyClass(...) extends {
var mutableArray: ArrayBuffer[Int] = ArrayBuffer.fill(5)(0)
} with SomeClass(..) {
Probably you are hitting the infamous "one question FAQ" about initialization order.
If the method is invoked by the superclass constructor, then your initialization happens after that, resetting the data to zero.
Related
I have following two classes.
class A (name: String) {
}
object A {
}
According to definition of Singleton, we can have only one object of that type. However I am able to create two different objects of type A using following piece of code.
object B {
def main(args: Array[String]): Unit = {
val a = new A("Vinod")
println(a)
val b = new A("XYZ")
println(b)
}
}
can someone please explain me, where my understanding is not correct?
An object by itself is a singleton. It has its own class and no other instance of the same class exist at runtime.
However, the pattern you describe here is different: object A is not an instance of class A unless you make it so using object A extends A. You could make it the only instance of class A by making class A a sealed class, but this is unnecessary in almost all cases.
If you really want the singleton pattern, drop the class and use only object A, all of its members will be "static" in the sense of Java.
Note that the actual type of object A can be referred to as A.type, which by default is completely unrelated to type A if class A exists. Again, A.type could be a subtype of A if you explicitly make it so.
The companion object is not an instance of the companion class. They're not even the same type.
class A
object A {
var state = 0
def update() :Unit = state = state + 1
}
val abc :A = new A //instance of class A
val xyz :A.type = A //2nd reference to object A
// both reference the same singleton object
xyz.update() //res0: Unit = ()
A.state //res1: Int = 1
abc.state //Error: value state is not a member of A$A2521.this.A
the companion object can be thought of as the static space of a class. if you want to make A a singleton you can make it an object rather than a class
new A refers to class A (which is not a singleton), not to object A. You can easily check it: if you remove class A, the new A lines will no longer compile.
Also note that objects aren't necessarily singletons: they can be nested inside classes or traits, in this case there is one for each instance of the outer type.
I want to have a var in a singleton object that I want to read from everywhere but only write into it from another singleton object (which is a companion object, but I don't think it matters here). Thus I put both objects into one file MyClass and made the var private but opened it up to the scope of the file with private[MyClass].
As a toy example: Everything is in the same file "MyClass.scala":
object OtherObject {
private[MyClass] var myvar = 0.0
def variable = myvar
}
object MyClass{
def setmyvar(myvar: Double): Unit = {
OtherObject.myvar = 2.0
}
}
class MyClass { ... }
This does not work however. I get the error "MyClass is not an enclosing class". How can I do what I want to do?
This will be not a companion object. You can have companion of class and object, both sharing the same name. Thus the error.
Putting that aside, you can achieve that what you asked for, by having both objects in the same package and limiting access with private to that package, or wrapping those objects with another one, and setting appropriate private modifier, like here:
object MyWrapper {
object OtherObject {
private[MyWrapper] var myvar = 0.0
def variable = myvar
}
object MyClass{
def setmyvar(myvar: Double): Unit = {
OtherObject.myvar = myvar
}
}
}
And then it works:
scala> MyWrapper.OtherObject.variable
res3: Double = 0.0
scala> MyWrapper.MyClass.setmyvar(3)
scala> MyWrapper.OtherObject.variable
res5: Double = 3.0
although it isn't especially elegant piece of code
but opened it up to the scope of the file
A file doesn't define a scope in Scala, period. So you can't make something writable only within the same file.
(There are actually three cases where files are relevant to scope that I can think of:
Top-level package statements have the rest of the entire file as their scope.
A class and an object with the same name are only companions if they are in the same file.
sealed traits or classes can only be extended in the same file.
None of them are useful for your question.)
A companion object must be defined inside the same source file as the class. Both should have same name. one should be class and another should be object type. Then only we can call it as companion.
object MyClass {
private[MyClass] var myvar = 0.0
def variable = myvar
}
class MyClass{
def setmyvar(myvar: Double): Unit = {
// your logic
}
}
http://daily-scala.blogspot.in/2009/09/companion-object.html
I haven't been able to find anything in the language definition that explains the initialisation of a class in Kotlin.
import java.util.Properties
fun main(args: Array<String>) {
val out = MyClass()
out.fn()
}
class MyClass {
private val a = Properties() // 1
init {
fn()
}
public fun fn() {
println("Fn called. a = $a")
}
// private val a = Properties() // 2
}
The results of running this program change depending whether the property is initialised at (1) or at (2).
I'm surprised that the declaration order is relevant in the language and would like to understand the decisions behind this. My expectation would be that properties are initialised before the constructor body is invoked.
My expectation would be that properties are initialised before the constructor body is invoked.
Well, init block is not a constructor. It is a different construct which allows you to perform the initialization of the object and they [init blocks] are performed in the declaration order with the property initializers.
Constructors are a different beast ant they are performed after all the properties were initialized and all init blocks were performed. Look at the following example:
class A(val value: Int) {
constructor(): this(0) {
println("Constructor")
}
init {
println("Init block")
}
}
fun main(args: Array<String>) {
val a = A()
}
Output is:
Init block
Constructor
You can place the init block wherever you want: before the constructor or after it; it will always be performed before the A's constructor (secondary constructor, in this example).
Simply put: when an instance of a class is created, (almost) firstly runs the constructor of the parent class (if present), then the primary constructor.
The primary constructor executes code declared in the class body from the top to the bottom. Also the names became available by the same rule:
class Foo(a: String = "might be first"
val b: String = "second" + a) : Boo(a + b + "third"){
var c = a + "fourth" + b
init {print("fifth: $c")}
val d = "sixth"
init {print("seventh: the end of the primary constructor"}
}
If you invoke a secondary constructor, then it works after the primary one as it is composed in the chain (similar to invoking the parent constructors).
I'm working on an automatic mapping framework built on top of Dozer. I won't go into specifics as it's not relevant to the question but in general it's supposed to allow easy transformation from class A to class B. I'd like to register the projections from a class's companion object.
Below is a (simplified) example of how I want this to work, and a Specs test that assures that the projection is being registered properly.
Unfortunately, this doesn't work. From what I can gather, this is because nothing initializes the A companion object. And indeed, if I call any method on the A object (like the commented-out hashCode call, the projection is being registered correctly.
My question is - how can I cause the A object to be initialized automatically, as soon as the JVM starts? I don't mind extending a Trait or something, if necessary.
Thanks.
class A {
var data: String = _
}
class B {
var data: String = _
}
object A {
projekt[A].to[B]
}
"dozer projektor" should {
"transform a simple bean" in {
// A.hashCode
val a = new A
a.data = "text"
val b = a.-->[B]
b.data must_== a.data
}
}
Short answer: You can't. Scala objects are lazy, and are not initialized until first reference. You could reference the object, but then you need a way of ensuring the executing code gets executed, reducing the problem back to the original problem.
In ended up doing this:
trait ProjektionAware with DelayedInit
{
private val initCode = new ListBuffer[() => Unit]
override def delayedInit(body: => Unit)
{
initCode += (() => body)
}
def registerProjektions()
{
for (proc <- initCode) proc()
}
}
object A extends ProjektionAware {
projekt[A].to[B]
}
Now I can use a classpath scanning library to initialize all instances of ProjektionAware on application bootstrap. Not ideal, but works for me.
You can force the instantiation of A to involve the companion object by using an apply() method or some other sort of factory method defined in the object instead of directly using the new A() constructor.
This does not cause the object to be initialized when the JVM starts, which I think as noted in another answer can't generally be done.
As Dave Griffith and Don Roby already noted, it cannot be done at JVM startup in general. However maybe this initialization could wait until first use of your framework?
If so, and if you don't mind resorting to fragile reflection tricks, in your --> method you could obtain reference to the companion object and get it initialize itself.
You can start at Getting object instance by string name in scala.
We could use this sort of a way to ensure that companion object gets initialized first and then the class gets instantiated.
object B {
val i = 0
def apply(): B = new B()
}
class B {
// some method that uses i from Object B
def show = println(B.i)
}
// b first references Object B which calls apply()
// then class B is instantiated
val b = B()
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.