Why can't I have a private var / val with the same name as a getter / setter? or how to desugar implicit getters / setters - scala

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.

Related

Is it good practice to use #BeanProperty in Scala instead of defining getter/setter functions?

Defining data members in a class that can be publicly accessed/modified
var _foo: Int = _
def foo_(foo: Int) = _foo = foo // setter function
def foo = _foo // getter function
Is it a good practice to convert this using annotation #BeanProperty?
import scala.reflect.BeanProperty
#BeanProperty var foo: Int = _
and when to use this annotation and when not to?
There's some redundancy in your first example, since defining a var already results in the generation of getters and setters. For example, if we compile this class:
class Foo {
var foo: Int = _
}
Then javap -private Foo shows the following:
public class Foo {
private int foo;
public int foo();
public void foo_$eq(int);
public Foo();
}
Unless you have custom logic that you need to fit into your getters or setters (in which case it's often a good idea to consider more descriptive method names, anyway), you shouldn't need to define them manually.
The scala.reflect.BeanProperty annotation (or scala.beans.BeanProperty on 2.11) doesn't have any effect on the generation of the foo() and foo_$eq(int) methods—the compiler will generate these for a var foo: Int whether or not you use the annotation. The annotation simply adds getFoo and setFoo aliases for these methods. If you need these aliases, use the annotation, and if you don't, don't.
To summarize best practices:
Don't use var.
If you have to use var, you can (and should) avoid defining your own getters and setters.
Use the BeanProperty annotation only if you're implementing an interface with getFoo and setFoo-style method signatures, or if you're expecting your code to be called from Java (where calling methods with names like foo_$eq is inconvenient).
#BeanProperty is meant for Java interoperability, in particular with reflection-based Java frameworks expecting get and set methods.
Do not use it if you're staying in the Scala world. Use Scala getters (def foo) and setters (def foo_=) instead.

Scala mutator naming conventions and requirements

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. ¯\_(ツ)_/¯

scala method name as variable name [duplicate]

This question already has answers here:
Rename JSON fields used by MappingJacksonJsonView in Spring
(2 answers)
Closed 7 years ago.
I want to define case class demo(notify: String), but my IDE (IntelliJ IDEA) complains that "notify cannot override final member".
I know that notify is a member method of AnyRef and the IDE may confuse variable name for method name. I need a notify field, how can I do that?
This isn't a problem with the IDE. A Scala class can't have conflicting symbols, whether or not they are methods or fields. For example, the following won't compile:
class Foo {
val bar = 1
def bar() = "bar"
}
notify is defined on AnyRef, and furthermore it is final, so you don't really have any great options here!
You can name the variable something different, of course:
case class Foo(_notify: String)
If you insist on the variable name, you can also extends AnyVal, but only if you have exactly one val parameter:
case class Foo(notify: String) extends AnyVal
You might be looking for the feature that allows you to escape keywords with the grave accent:
case class Foo(`val`: String)
This would allow you to use a keyword (and some other normally illegal variable names) as a variable name. This doesn't apply to your example, since notify isn't a keyword – it's an already used symbol on the class!
You can also come up with a solution where notify is private to the class, but that won't work with case classes or most reasonable use cases.
Ignoring your use case, a field called notify:
scala> class X(private[this] val notify: Int) { def f = notify * 2 }
defined class X
scala> new X(5).f
res1: Int = 10
scala> :javap -prv X
Binary file X contains $line6.$read$$iw$$iw$X
[snip]
{
private final int notify;
flags: ACC_PRIVATE, ACC_FINAL
public int f();
flags: ACC_PUBLIC
[snip]

Is there any advantage to definining a val over a def in a trait?

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.

Constructor arguments are visible in entire class -- a feature or a bug?

Consider such code (this is just example not real code):
class Foo(url : String) extends Bar(url)
{
def say() { println(url) }
}
It compiles and it works. With nonsense results "of course". I am too newbie to judge, but for me it serves no purpose but confusion -- by definition it is impossible that the argument of the constructor could be reachable directly in another method.
Could someone more experience in Scala could point out condition when it might work or make sense? Or confirm my suspicion this is flaw in current Scala compiler.
Update
class Bar(val Url : String)
{
}
Why "nonsense". Because my will (no "var" and no "val" in Foo) was to just pass the argument, nothing else. So when I actually use the constructor argument it is just matter of what entity I use by mistake. When you write on purpose, you hit the jackpot each time, but if you don't (i.e. you make a mistake in spelling), you use entities by random. It is not the code does not make sense, it is the computation just does not make sense, I could roll a dice as well. There is a method scope, and I don't see a reason why there shouldn't be constructor scope.
Update -- workaround
So it seems this evil construct is really part of the language (by design). As UserUnknown and Tomasz Nurkiewicz suggested the only line of defense against making stupid typo is convention, however lower-upper case is not good. "A" and "a" differ a lot, but "U" and "u" not much. Introducing one special character (as Tomasz showed) is much better, because it is possible to visually detect fishy usage of constructor argument.
I will use "$" for "just-passing" constructor arguments, it is harder to type for me, and you don't see this character too often in the code.
Thank you for the answers!
Why it is evil? Because implicit actions should be allowed explicitly by users -- good examples are "dynamic" in C#, implicit conversions in Scala. And examples of breaking this rule which led to tons of problems are -- implicit conversions to bool in C++, implicit constructors in C++, declaration by usage in Perl. And this particular case is very, very close to the mentioned perlism, in Perl finally there was change in interpreter to detect such misusages, why Scala repeated the same mistake? I wonder.
Your suspicions are entirely merit-less. This is by design.
Parameters of a class are part of the class. They'll be preserved as field if necessary (such as in your example), or not if they are never used outside construction.
So, basically, if you don't need it as a field, it won't be. If you do, it will. And you'll never write a single extra character of code to tell the compiler what it can figure out by itself.
It's not a bug, it's a feature. In fact, a really nice one. Need an example how useful it is? Here is how I use it with Spring and dependency injection via constructor:
#Service
class Foo #Autowired() (bar: Bar, jdbcOperations: JdbcOperations) {
def serverTime() = bar.format(jdbcOperations.queryForObject("SELECT now()", classOf[Date]))
}
Equivalent code in Java:
#Service
public class Foo
{
private final Bar bar;
private final JdbcOperations jdbcOperations;
#Autowired
public Foo(Bar bar, JdbcOperations jdbcOperations)
{
this.bar = bar;
this.jdbcOperations = jdbcOperations;
}
public String serverTime()
{
return this.bar.format(this.jdbcOperations.queryForObject("SELECT now()", Date.class));
}
}
Still not convinced?
Short tutorial:
class Foo(var x: Int, val y: Int, z: Int) {
println(z)
//def zz = z
}
x will become a variable with getters and setter. y will become an immutable variable and z will become an immutable variable only if zz method is uncommented. Otherwise it will remain a constructor argument. Neat!
UPDATE: I see your point now! The following code works as expected by accessing url variable in base class:
class Bar(val url)
class Foo(_url : String) extends Bar(_url)
{
def say() { println(url) }
}
I agree, this is both ugly and is asking for trouble. In fact I once hit this problem myself when using Scala classes as Hibernate entities - I used constructor parameter instead of field in base class which caused duplicated field to be created: one in base class and one in derived class. I wouldn't even notice but Hibernate was screaming at runtime that duplicated column mapping was defined.
So I have to somewhat agree with you - this is somehow confusing and might be error-prone. This is the price you pay for "implicitness" and concise code.
However note that no modified and val modifier before constructor argument are different. Without modified immutable field is created, while val additionally adds getter.
Scala creates a field from a constructor parameter when such an parameter is referenced by a method in the class. I'm having trouble finding fault with the way that this works.
For the simple case everything works as expected:
scala> class Bar(val url: String)
defined class Bar
scala> class Foo(url: String) extends Bar(url) {
| def say() { println(url) }
| }
defined class Foo
scala> new Foo("urlvalue").say
urlvalue
If we introduce some confusion over the case of the constructor parameter this example still works as expected:
scala> class Bar(val Url: String)
defined class Bar
scala> class Foo(url: String) extends Bar(url) {
| def say() { println(url) }
| }
defined class Foo
scala> new Foo("urlvalue").say
urlvalue
Interestingly you might think that this has worked because it has introduced a lower-case url field in Foo in addition to the upper case Url in Bar, but that doesn't seem to be the case - the compiler seems to be smart enough to know that it can go to Url to get the value of url in say, as no lower case field is generated.
scala> :javap -private Bar
Compiled from "<console>"
public class Bar extends java.lang.Object implements scala.ScalaObject{
private final java.lang.String Url;
public java.lang.String Url();
public Bar(java.lang.String);
}
scala> :javap -private Foo
Compiled from "<console>"
public class Foo extends Bar implements scala.ScalaObject{
public void say();
public Foo(java.lang.String);
}
The only time I can see that this gets confusing is if you mis-spell a var field. In this case you do actually introduce a new field, and the two can get out of step.
scala> class Bar(var Url: String)
defined class Bar
scala> class Foo(url: String) extends Bar(url) {
| def say() { println(url) }
| }
defined class Foo
scala> val f = new Foo("urlvalue")
f: Foo = Foo#64fb7efa
scala> f.say
urlvalue
scala> f.Url = "newvalue"
f.Url: String = newvalue
scala> f.say
urlvalue
scala> :javap -private Foo
Compiled from "<console>"
public class Foo extends Bar implements scala.ScalaObject{
private final java.lang.String url;
public void say();
public Foo(java.lang.String);
}