I have an parent class, and several child classes. What I want is when specific setter methods are called on instances of the child classes, a boolean value for "is synchronized" in the parent class is set to false. It should be possible to create child classes in either a synchronized or an unsynchronized state.
This is what I came up with:
class A(protected var isSync: Boolean) {
}
class B(var value:String, isSync: Boolean) extends A(isSync) {
override def value_=(value:String): Unit = {
this.isSync = false
this.value = value
}
}
Now, this doesn't compile for a number of reasons: the assignment of value to this.value is ambiguous; the var annotation already defines value_=; and this.isSync references the local constructor field isSync, instead of the (writable) parent field.
This question on Stack Overflow pointed out that I should use __value (or any name that isn't value) as a private var in the constructor, and define the setter myself. After some more tinkering, I came up with the following code that compiles and works:
class A(protected var isSync: Boolean) {
}
class B(private var __value: String, private val __isSync: Boolean)
extends A(__isSync) {
def value = __value
def value_=(value: String) = {
this.isSync = false
this.__value = value
}
}
However, this code feels so rancid that by now I suspect I'm making a (if not more) fundamental mistake. Could anyone please correct me?
Thus the concrete questions are:
Are there (and if, which) fundamental flaws in what I'm trying to implement? For some context: the objects, when changed, can (and probably have to) be synchronized with a server.
What is the right/best way to pass parameters to a class you extend?
What is the right/best way to override the setter generated by var (or generally provide your own setter implementation)?
About question 1: I guess that you want to track whether the object has been changed since last time it was copied to the server, don't you? That's sensible, as long as the copy on the server cannot be modified: otherwise ensuring consistency of the replica is more complex (replica consistency is the keyword for googling, but I wouldn't recommend it).
For clarity, I would talking about being clean or dirty - synchronized reminds me too closely of the synchronized Java statement.
About question 2, you don't need to make __isSync a private val (which will be stored in the class), you can leave it as a constructor parameter. As long as it is not used (other than in the invocation of A's constructor) __isSync should not take additional space in instances of B. I removed the private val annotation there, obtaining this code which compiles correctly as expected.
class A(protected var isSync: Boolean) {
}
class B(private var __value: String, __isSync: Boolean)
extends A(__isSync) {
def value = __value
def value_=(value: String) = {
this.isSync = false
this.__value = value
}
}
About aesthetics and question 3: I would simply avoid the double underscore. Similar examples from Programming in Scala (Sec 18.2) simply use shorter names. They also use private[this] to prevent access to the member from other instances of the same class. Finally, you can remove {} after the class decl. in this example (even if maybe not in your code).
Thus we'd get code like this, which is close to the examples I already mentioned:
class A(protected var isSync: Boolean)
class B(private[this] var v: String, sync: Boolean)
extends A(sync) {
def value = v
def value_=(value: String) = {
isSync = false
v = value
}
}
Related
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 see some Scala code like this:
case class Team(private val members: List[User]) {
def removed(member: User): Team = {
Team(members.filterNot(_ == member))
}
def added(member: User): Team = {
Team(member :: members)
}
def allNames: List[String] = members.map(_.name)
}
You can see the Team is a case class, but it has a private field members. And in the body, it has several methods to construct a new Team, and a method allNames which export some information of the private members.
I'm not sure if the usage of case class is good, since I think a case class is a data class, we should not use private fields. For this case, I think a normal class is enough:
class Team(members: List[User]) {
def removed(member: User): Team = {
new Team(members.filterNot(_ == member))
}
def added(member: User): Team = {
new Team(member :: members)
}
def allNames: List[String] = members.map(_.name)
}
You can see I removed the case, and also private since for a normal class, the fields of constructor is private by default.
But I'm not sure if there is any good reason to write the code in the first approache.
Private vals in case classes are a little surprising because they're not as private as you might imagine if you think other ways of getting that value are just syntactic sugar.
In particular, pattern matching will give you the underlying value:
whatever match {
case Team(members) => println("I can see "+members.mkString)
}
And the value still plays a role in equality (even if you can't get it by name), and you can create copies with different values using copy.
Sometimes a private val is used to enforce best practices for that class, which is to only use pattern matching to get the values (e.g. because you will often want to pattern match other things, and this enforces consistency). Sometimes it's an indication that the programmer doesn't understand how it works and thinks its enforcing a complete lack of access to the val.
In Scala, a val can override a def, but a def cannot override a val.
So, is there an advantage to declaring a trait e.g. like this:
trait Resource {
val id: String
}
rather than this?
trait Resource {
def id: String
}
The follow-up question is: how does the compiler treat calling vals and defs differently in practice and what kind of optimizations does it actually do with vals? The compiler insists on the fact that vals are stable — what does in mean in practice for the compiler? Suppose the subclass is actually implementing id with a val. Is there a penalty for having it specified as a def in the trait?
If my code itself does not require stability of the id member, can it be considered good practice to always use defs in these cases and to switch to vals only when a performance bottleneck has been identified here — however unlikely this may be?
Short answer:
As far as I can tell, the values are always accessed through the accessor method. Using def defines a simple method, which returns the value. Using val defines a private [*] final field, with an accessor method. So in terms of access, there is very little difference between the two. The difference is conceptual, def gets reevaluated each time, and val is only evaluated once. This can obviously have an impact on performance.
[*] Java private
Long answer:
Let's take the following example:
trait ResourceDef {
def id: String = "5"
}
trait ResourceVal {
val id: String = "5"
}
The ResourceDef & ResourceVal produce the same code, ignoring initializers:
public interface ResourceVal extends ScalaObject {
volatile void foo$ResourceVal$_setter_$id_$eq(String s);
String id();
}
public interface ResourceDef extends ScalaObject {
String id();
}
For the subsidiary classes produced (which contain the implementation of the methods), the ResourceDef produces is as you would expect, noting that the method is static:
public abstract class ResourceDef$class {
public static String id(ResourceDef $this) {
return "5";
}
public static void $init$(ResourceDef resourcedef) {}
}
and for the val, we simply call the initialiser in the containing class
public abstract class ResourceVal$class {
public static void $init$(ResourceVal $this) {
$this.foo$ResourceVal$_setter_$id_$eq("5");
}
}
When we start extending:
class ResourceDefClass extends ResourceDef {
override def id: String = "6"
}
class ResourceValClass extends ResourceVal {
override val id: String = "6"
def foobar() = id
}
class ResourceNoneClass extends ResourceDef
Where we override, we get a method in the class which just does what you expect. The def is simple method:
public class ResourceDefClass implements ResourceDef, ScalaObject {
public String id() {
return "6";
}
}
and the val defines a private field and accessor method:
public class ResourceValClass implements ResourceVal, ScalaObject {
public String id() {
return id;
}
private final String id = "6";
public String foobar() {
return id();
}
}
Note that even foobar() doesn't use the field id, but uses the accessor method.
And finally, if we don't override, then we get a method which calls the static method in the trait auxiliary class:
public class ResourceNoneClass implements ResourceDef, ScalaObject {
public volatile String id() {
return ResourceDef$class.id(this);
}
}
I've cut out the constructors in these examples.
So, the accessor method is always used. I assume this is to avoid complications when extending multiple traits which could implement the same methods. It gets complicated really quickly.
Even longer answer:
Josh Suereth did a very interesting talk on Binary Resilience at Scala Days 2012, which covers the background to this question. The abstract for this is:
This talk focuses on binary compatibility on the JVM and what it means
to be binary compatible. An outline of the machinations of binary
incompatibility in Scala are described in depth, followed by a set of rules and guidelines that will help developers ensure their own
library releases are both binary compatible and binary resilient.
In particular, this talk looks at:
Traits and binary compatibility
Java Serialization and anonymous classes
The hidden creations of lazy vals
Developing code that is binary resilient
The difference is mainly that you can implement/override a def with a val but not the other way around. Moreover val are evaluated only once and def are evaluated every time they are used, using def in the abstract definition will give the code who mixes the trait more freedom about how to handle and/or optimize the implementation. So my point is use defs whenever there isn't a clear good reason to force a val.
A val expression is evaluated once on variable declaration, it is strict and immutable.
A def is re-evaluated each time you call it
def is evaluated by name and val by value. This means more or less that val must always return an actual value, while def is more like a promess that you can get a value when evaluating it. For example, if you have a function
def trace(s: => String ) { if (level == "trace") println s } // note the => in parameter definition
that logs an event only if the log level is set to trace and you want to log an objects toString. If you have overriden toString with a value, then you need to pass that value to the trace function. If toString however is a def, it will only be evaluated once it's sure that the log level is trace, which could save you some overhead.
def gives you more flexibility, while val is potentially faster
Compilerwise, traits are compiled to java interfaces so when defining a member on a trait, it makes no difference if its a var or def. The difference in performance would depend on how you choose to implement it.
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.
I wonder if it is possible to inherit auxiliary constructors in Scala?
I tested this code, and it complained
temp.scala:18: error: too many arguments for constructor Child: ()this.Child
val a = new Child(42)
^
abstract class Father {
var value: Int = 0
protected def setValue(v: Int) = {
value = v
}
protected def this(v: Int) = {
this()
setValue(v)
}
}
class Child extends Father {
}
val a = new Child(42)
But if i put
protected def this(v: Int) = {
this()
setValue(v)
}
in the Child class, everything is all right.
Absolutely not, and your example demonstrates why. You've introduced a mutable variable value that may or may not be initialised - depending on the exact constructor used.
This is a potential source for a great many problems, and so Scala made the decision that all object creation should ultimately be directed via the primary constructor, this ensuring consistent initialisation.
If you want value to have a default value, then you can specify it as a default parameter (in 2.8+):
abstract class Father(val value : Int = 0)
or you can use the auxiluary constructor to achieve the same effect in Scala 2.7:
abstract class Father(val value : Int) {
def this() = this(0)
}
With Father defined in either of the above ways, the following definitions of child are both valid:
class Child(v:Int) extends Father(v)
class Child extends Father()
You can also make value a var if you absolutely have to, but I strongly advise against it.
If the semantics of value mean that it's valid to not be initialised, then the correct Scala idiom is to declare it as Option[Int]:
abstract class Father(val value : Option[Int] = Some(0))
Your Child constructor have no parameter and you are trying to instanciate it with one ! You have to declare a parameter in your Child constructor and then pass it to the Father class, for example:
class Child(v:Int) extends Father(v) {
}
val a = new Child(42)