I have a scala class:
class Foo {
def this(st: String) {
var baz = List[String]()
var jaz = "one" + st
// more code logic
}
}
First above code does not compile. Secondly I want baz and jaz to be private variables local to the lone constructor above and not instance variables.
How to solve this problem?
It does not compile because the first thing that MUST happen in an auxiliary constructor is a call to the primary constructor. I don't understand the second question, since the variables you have declared already ARE private
Something like this is maybe what you are looking for?
class Foo(st: String) {
val myInstance = {
var baz = List[String]()
var jaz = "one" + st
jax + baz.mkString(":")
}
}
The body of your class is the constructor. If you want to have some temporary values, you can declare a block with just about anything you want; that block can return a value, and you can store that value in an instance variable, in this case myInstance.
Related
I have a situation, where in Kotlin I want to take the name of a reference, modify it, and then call a function with the object, which corresponds with the modified name. For example:
val a = "Foo"
val aAlt = "Bar"
fun doSomething(s: String){
println(s.*addAltToStringName()* )
}
So that by calling
doSomething(a)
the result is
Bar
I know, that doing something "untyped-scripty" like this in an object oriented language is dangerous, but I have other checks to prevent Nullpointers etc.
Thanks!
This can be done with reflection, but only if the argument to the function is property reference, so you can get its name. The String object itself would provide no way to retrieve info about whatever variables might hold references to it. In other words, your property a references a String object, but that String object itself has no name or knowledge of the property that references it.
class Test {
val a = "Foo"
val aAlt = "Bar"
fun doSomething(s: KProperty<*>){
val propertyName = s.name + "Alt"
val propertyValue = Test::class.memberProperties.find { it.name == propertyName }?.get(this)
println(propertyValue)
}
}
fun main() {
val test = Test()
test.doSomething(test::a)
}
It seems like having uninitialized members in the object body is forbidden in Scala objects..
I wanted to do something like (if it was in Java)
class MyClass {
private String str;
private String reassignString(String value) {
str = value;
}
I'm restricted on changing this code from object to class (since this repo is used by many teams) - what's a good Scala way to handle this kind of situation? Sorry the question is really vague.
Here is another bad idea:
object Lazy {
lazy val v = if (underlying ne null) underlying else ???
var underlying: String = null
}
Try(Lazy.v)
Lazy.underlying = "yes"
Try(Lazy.v)
Lazy.underlying = null
Try(Lazy.v)
The point is that the lazy val gets more than one shot at initialization, but is successfully initialized only once, if that's what you want.
Note that default initializer syntax is on its way out. They want you to write null if you want null.
My preferred default initializer:
var underlying: String = underlying
just to break the ice at dinner parties.
Uninitalized values are a bad idea, so str needs to be initialised to a valid value.
There are three obvious options:
Give str the default value
private var str: String = _
Pick you own default
private var str: String = "undefined"
Use Option
class MyClass {
private var str: Option[String] = None
private def reassignString(value: String): Unit = {
str = Some(value)
}
}
str in this Java code is initialized, to null. Scala simply requires you to make it explicit whether that's what you want.
Is the below Scala class is mutable or immutable?
I believe that its immutable as I can't edit the variables or access them once its created but whats making me doubt myself is the fact that it returns the current instance of a variable using its functions. It also does not have final in front of it which is further making me doubt myself.
class person(name:String, dob:String){
def getName = name
def getDob = dob
def display() = {
println("Name "+name+" dob: "+dob)
}
}
Thanks,
You have a misconception with the term Immutable:
I believe that its immutable as I can't edit the variables or access
them once its created
That's the definition of a private thing (method, variable, ...). Immutability refers to the fact that you cannot mutate state, that is, you can't change the value of something unless you create a new instance of it.
Let's see it with an example:
trait Foo{
def myMutableValue: Int
}
class Clazz extends Foo{
var myMutableValue = 1
def changeState(): Int = {
myMutableValue += 1
myMutableValue
}
}
val bar = new Clazz
bar.changeState() // myMutableValue = 2
bar.changeState() // myMutableValue = 3
bar.changeState() // myMutableValue = 4
bar.myMutableValue // myMutableValue = 4
With that example, in your instance of Clazz (bar) you're changing the state of a class attribute, in this case myMutableValue is changing its value every time I invoke changeState.
Please note that the class is public by default and changeState is also public and that doesn't means that is immutable.
Now, let's see an immutable approach:
trait Foo{
def myMutableValue: Int
}
class Clazz extends Foo{
val myMutableValue = 1
def changeState(): Int = myMutableValue + 1
}
val instance = new Clazz
instance.changeState() // myMutableValue = 2
instance.changeState() // myMutableValue = 2
instance.changeState() // myMutableValue = 2
instance.myMutableValue // 1
With this approach, every call to changeState will evaluate to 2, no matter how many times I call the function. That is, because we're dealing with an immutable value (val myMutableValue = 1). Every invocation of changeState will perform the evaluation and return a copy of that value. You're not modifying in any way the value of myMutableValue.
Please take a look to this and this.
Also, please take a look at your code, you have some errors:
By convention, class name should be capitalized (Person instead of person).
You don't need to reassign your class values with def (def getNameand def getDob). You can use class values as is.
Lastly:
It also does not have final in front of it which is further making me
doubt myself.
Again, you're talking about different things. final, as in Java, is a modifier to prevent your class to be extended. It doesn't relate in any way to immutability In adition, if you want to prevent mutability in your subclass you have to make all their members final (see this).
Since your example is coded in Scala you have all the tools that the language itself offers at your disposal (e.g. val, sealed, final)
Please note that I've used a trait to explain the possible use of def.
EDIT: about final modifier and immutability
Thanks to #Silvio Mayolo and #puhlen for the comments and clarification about final
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).