I am having some trouble understand the naming in Scala with respect to mutators. Here is the part that I am having trouble understanding:
class Company {
private val _name: String = _
def name = _name
def name_=(name: String) {
_name = name
}
}
So I understand that the _name is the private String, and the first def name is the getter/accessor while the second is the setter/mutator. Essentially, I understand what the code means and does, but I am not sure what is personal preference vs code standards/the required way to do it. Will all mutators have the _ suffix and is it standard to prefix private attributes with an underscore or is that personal preference?
Or can I just define the mutator as the following?
def name=(name: String) {
_name = name
}
Similarly, do I have the prefix the private val with the underscore or could I just change it to:
def name=(name: String) {
name = name
}
I got the above code from Scala Naming Conventions and Daniel Spewak's Accessors/Mutators
These are all good questions. Some of them are covered by the article from the Scala documentation you've liked, specifically in the part about Accessors/Mutators.
Naming of mutator methods
In a nutshell, the name_= form is not special syntax but rather a naming convention enforced by the specification.
Let's look at what scalac produces at the JVM bytecode level when you declare a plain old var. Understanding the bytecode produced by scalac is by no means necessary to understand the higher-level workings of the language, but many people learning Scala have some experience with Java and, though that, some intuition of what is possible in the JVM and what isn't. I think this is the closest we can get to as the why of some of the decisions that were made in the specification of Scala.
Here I have a source file called Var.scala:
trait Var {
var name: String
}
I compile the source to a class file and decompile it using javap:
$ scalac Var.scala
$ javap Var.class
Compiled from "Var.scala"
public interface Var {
public abstract java.lang.String name();
public abstract void name_$eq(java.lang.String);
}
As we can see, a var in a trait declares two JVM methods, a getter, and a setter. The getter takes the name of the var, while the setter has a bit of a weird name. Here, $eq is just how an = in a Scala identifier is encoded by scalac in the class file it produces. This is part of the Scala specification and is required for binary compatibility between different compilation units.
So the name of the setter as seen from Scala is simply name_=. This is also part of the Scala specification. When we write a statement that sets the value of a var, a call to a method with a name of that form is generated. When we write a statement that just reads the var, a call to the first method is generated.
Instead of declaring a var, we could just as well declare those two methods directly:
trait ValAndDef {
val name: String
def name_=(newName: String): Unit
}
Compiling and decompiling this will show the exact same methods as before. There is also nothing preventing you from declaring only one of those methods, which would create a member which can only be read but not written, or vice versa.
Naming of the private packing field
Until now, I've only talked about declaring a field. Implementing the field means also adding storage to the var or implementing the methods when declared directly. Declaring a var in a class instead of a trait will automatically add a field for storing the value of the var:
class VarClass {
var name: String = _
}
$ javap -private VarClass.class
Compiled from "VarClass.scala"
public class VarClass {
private java.lang.String name;
public java.lang.String name();
public void name_$eq(java.lang.String);
public VarClass();
}
If you decide to implement the field using a pair of methods, you will have to declare such a private field yourself. The Scala specification does not say anything about how that field should be named in that case (it is private and thus not part of any interoperability concern).
The only thing "official" I can find is a paragraph in the article I linked at the top, which advocates the _name naming pattern for the backing field, while also stating:
While Hungarian notation is terribly ugly, it does have the advantage of disambiguating the _name variable without cluttering the identifier.
So it is up to you whether you want to follow that guidance or not. ¯\_(ツ)_/¯
Related
I am trying to write immutable code in Dart. Dart wasn't really built with immutability in mind, that's why I need to write a lot of boilerplate in order to achieve immutability. Because of this, I got interested in how a language, like Scala, which was built around the concept of immutability, would solve this.
I am currently using the following class in Dart:
class Profile{
List<String> _inSyncBikeIds = []; // private field
String profileName; // public field
Profile(this.profileName); // You should not be able to pass a value to _inSyncBikeIds
void synchronize(String bikeId){
_inSyncBikeIds.add(bikeId);
}
bool isInSync(String bikeId){
return _inSyncBikeIds.contains(bikeId);
}
void reset(){
_inSyncBikeIds = [];
}
}
The same class in immutable:
class Profile{
final List<String> _inSyncBikeIds = []; // private final field
final String profileName; // public final field
factory Profile(String profileName) => Profile._(profileName); // You should not be able to pass a value to _inSyncBikeIds
Profile._(this._inSyncBikeIds, this.profileName); // private contructor
Profile synchronize(String bikeId){
return _copyWith(inSyncBikeIds: _inSyncBikeIds.add(bikeId);
}
bool isInSync(String bikeId) {
return _inSyncBikeIds.contains(bikeId);
}
Profile reset(){
return _copyWith(inSyncBikeIds: []);
}
Profile copyWith({
String profileName,
}) {
return _copyWith(profileName: profileName)
}
Profile _copyWith({
String profileName,
List<Id> inSyncBikeIds,
}) {
return Profile._(
profileName: profileName ?? this.profileName,
inSyncBikeIds: inSyncBikeIds ?? _inSyncBikeIds);
}
}
What I understand from Scala so far, is that for every class a copy method is automatically created. In order to be able to change a field using the copy method, it needs to be part of the constructor.
I want the field _inSyncBikeIds to be final (val in Scala). In order to change the value of the field _inSyncBikeIds I need to create a copy of the object. But in order to use the copy method, to change the field, it needs to be part of the constructor of the class, like class Profile(private val _inSyncBikeIds, val profileName). But this would then break encapsulation, because everyone can create an object and initialize _inSyncBikeIds. In my case, _inSyncBikeIds should always be an empty list after initialization.
Three questions:
How do I solve this in Scala?
When I use the copy method inside the class, can I change private fields using the copy method?
Does the copy method in Scala copy private fields as well (even when they are not part of the constructor, you can't mutate that private field then of course)?
Scala comes from a tradition that tends to view immutable data as a license for free sharing (thus public by default etc.). The interpretation of encapsulation is more that code outside an object not be able to directly mutate data: immutable data regardless of visibility satisfies this.
It's possible to suppress the auto-generated copy method for a case class by making it abstract (nearly always sealed abstract with a private constructor). This is commonly used to make the apply/copy methods return a different type (e.g. something which encodes a validation failure as a value without throwing an exception (as require would)), but it can be used for your purpose
sealed abstract case class Profile private(private val _inSyncBikeIds: List[String], profileName: String) {
def addBike(bikeId: String): Profile = Profile.unsafeApply(bikeId :: _inSyncBikeIds, profileName)
// Might consider using a Set...
def isInSync(bikeId: String): Boolean = _inSyncBikeIds.contains(bikeId)
def copy(profileName: String = profileName): Profile = Profile.unsafeApply(_inSyncBikeIds, profileName)
}
object Profile {
def apply(profileName: String): Profile = unsafeApply(Nil, profileName)
private[Profile] def apply(_inSyncBikeIds: List[String], profileName: String): Profile = new Profile(_inSyncBikeIds, profileName) {}
}
unsafeApply is more common for the validation as value use-case, but the main purpose it serves is to limit the concrete implementations of the abstract Profile to only that anonymous implementation; this monomorphism has beneficial implications for runtime performance.
Notes: case classes are Serializable, so there is a Java serialization hole: in application code this is solvable by never ever using Java serialization because it's broken, but it makes up for being broken by being completely evil (i.e. if you have a Scala application that uses Java serialization, you should probably re-evaluate the choices that led you there).
There's no way to encode sealedness in JVM bytecode AFAIK (Scala uses an annotation, IIRC, so Scala will limit extension of Profile to that compilation unit but, e.g, Kotlin won't), nor is the private[Profile] access control encoded in a way that JVM languages which aren't Scala will enforce (the unsafeApply method is actually public in the bytecode). Again, in application code, the obvious question is "why are you trying to use this from Java/Kotlin/Clojure/...?". In a library, you might have to do something hacky like throw an exception, catch it and inspect the top frames of the stack, throwing again if it's not hunky-dory.
I have no idea if it is possible in dart, but in scala this would be done with a private constructor:
class Profile private (val _foo: Seq[String], val bar: String) {
def this(bar: String) = this(Nil, bar)
}
This lets you define
private copy(foo: Seq[String], bar: String) = new Profile(foo, bar)
This is fine as long the class is final. If you subclass it, badness ensues: Child.copy() returns an instance of Parent, unless you override copy in every subclass, but there is no good way to enforce it (scala 3 admittedly has some improvement over this).
The generated copy method you mentioned only works for case classes. But subclassing a case class would lead to some even more interesting results.
This is really rarely useful though. Looking at your code for instance, if I read the ask correctly, you want the user to not be able to do
Profile(List("foo"), "bar") but Profile("bar").synchronize("foo") is still possible even though it produces exactly the same result. This hardly seems useful.
In Chapter 19 ,"Programming in scala 2nd edition",how to explain the bold sentences ?
object private members can be accessed only from within the object in
which they are defined. It turns out that accesses to variables from
the same object in which they are defined do not cause problems with
variance. The intuitive explanation is that, in order to construct a
case where variance would lead to type errors, you need to have a
reference to a containing object that has a statically weaker type
than the type the object was defined with. For accesses to object
private values, however,this is impossible.
I think the most intuitive way to explain what Martin is trying to say is to look at arrays in Java. Arrays in Java are covariant but don't type check according to covariance rules. This means they explode at runtime instead of compile time:
abstract class Animal {}
class Girafee extends Animal {}
class Lion extends Animal {}
public class Foo {
public static void main(String[] args) {
Animal[] animals = new Girafee[10];
animals[0] = new Lion();
}
}
The fact that I can do this is because:
Java doesn't restrict this at compile time (due to a design decision)
I have a reference to the underlying array which allows me to manipulate it's internal values
This doesn't hold when talking about private fields of a class from the outside.
For example, assume the following class:
class Holder[+T](initialValue: Option[T]) {
private[this] var value: Option[T] = initialValue
}
When creating an instance of Holder, I am not visible to it's internal fields, thus I cannot manipulate them directly like I did with the Java array. This way, the compiler makes sure they are protected, and each manipulation to the field will have to be through a method, where the type checker is strict and doesn't allow funky business.
When inheriting from a Java class with public members, using scala's override modifier raises compilation error like so:
Error:(67, 22) overriding variable userId in class Logon of type String;
value userId has incompatible type
override val userId = s.user
^
The java class looks something along the following lines:
public class Logon {
public String userId = "";
}
and the scala code:
class MyLogon extends Logon {
override val userId : String = "abc"
}
Removing the modifier results in:
Error:(72, 7) overriding variable userId in class Logon of type String;
value userId needs `override' modifier
val userId: String = s.user
^
Why is this? Is it a bug? There are related questions e.g. 16607517 but these seem to be changing the visibility of the fields; that's not the case here - they're all public.
Believe this is with scalac-2.10.4.
It is impossible to override public fields defined in Java because of how it is implemented in Scala:
A public field (val user: String) is represented internally as a combination of private field (say, private val user$1: String) and public accessor method (def user: String = user$1). It is not allowed to override a field with a method, thus the compile error.
There is currently no way to omit the public accessor method generation in Scala, so you'll have to find other ways to implement what you want - either by defining a common trait or interface, or by using another field name, or by wrapping the Java Logon into a Scala Logon with proper superclass constructs.
Scala interoperates extremely well with Java, but the interop is not perfect, unfortunately.
You cannot override member variables.
This should not be confused with how scala allows to override val & var which works because scala compiler generates getter and setter methods for them.
I'm sure it's a duplicate, but I couldn't find it.
Consider this class
class Test1(var param: Int)
Scala generates a getter and a setter, and makes the param private.
It can be shown using javap for example:
public class Test1 {
private int param;
public int param();
public void param_$eq(int);
public Test(int);
}
I was trying to write the desugared version of it with explicit getters / setters but couldn't do so 100% the same way as the private var had a naming collision with the getter.
class Test2(private[this] var param:Int) {
def param:Int = this.param
def param_= (param:Int) {this.param = param}
}
This is the error:
ambiguous reference to overloaded definition,
both method param in class Test2 of type => Int
and variable param in class Test2 of type Int
match expected type Int
def param:Int = param
^
This of course works (renaming private member to _param)
class Test3(private[this] var _param:Int) {
def param:Int = this._param
def param_= (param:Int) {this._param = param}
}
But generates this slightly different bytecode of course (since we had to rename param to _param):
public class Test3 {
private int _param;
public int param();
public void param_$eq(int);
public Test3(int);
}
Is there any way to reach the same bytecode as the example in Test1 while using explicit getter / setters as in Test2?
In Scala methods and fields share the same name space. This is a little confusing for converts coming from Java or other languages which have separate name space for each.
But it follows the Uniform Access Principle i.e. the user of a class can't tell if he is actually calling a def or a val (or a var) when used without parenthesis. This also means you can switch implementations between val an def without clients being affected. (I'm not sure if they'd have to get recompiled, but the source code can stay as it is.
Actually, you can!
Here is an answer that does exactly that to good effect.
There you will find a private var and an accessor with the same name.
private[this] var state
private final def state()
Note the parens on the definition of the accessor, which are not needed at the use site.
Under the covers, the local field has that LOCAL_SUFFIX_STRING, which is an evil space. See the Test3 members, below, which strips away the covers to bare all.
On the getter side, you can add parens. That breaks the saccharin setter, apparently. Can you live without sugary assignment syntax?
When you reference x.param, the compiler will supply parens, see #alexiv 's comment elsewhere on uniform access or the SO answer mentioned above.
import reflect.runtime.currentMirror
import reflect.runtime.universe._
class Test2(private[this] var param: Int) {
def param(): Int = param
def param_=(param: Int) { this.param = param }
}
val x = new Test2(1)
Console println x.param
x.param_=(2)
Console println x.param
class Test3(var param: Int)
val ps = typeOf[Test3].members filter (m => m.name.toString.startsWith("param")) map (m => s"'${m.name.toString}'")
Console println ps
Console println (typeOf[Test3].members filter (_.name.toString.endsWith(nme.LOCAL_SUFFIX_STRING)))
Note that the other answers suggest that Scala only distinguishes terms and types, neglecting to mention that symbols (obviously) can be overloaded.
You may have read that overloading is evil! That may be so, but whatever you do in the privacy of your own private members is entirely your own affair.
(Updated to suggest that even if the question is somewhat duplicated somewhere, this is still a fun and informative answer.)
I think variable and method are treated the same, the variable param is like a method without parameters, and the method param is the same, so just like the error indicates: ambiguous reference to overloaded definition.
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.