Overriden method can call on inherited private getter, but not inherited private setters - scala

I think this could apply to both Java and Scala, but - a week in to learning Scala so trying that out. I have this:
class myBaseClass {
private var member: Int = 100
def doStuff(): Unit ={
checkMember()
alterMember(5)
}
private[this] def checkMember(): Unit = {
//throws exception if member < 0
}
private[this] def alterMember(i : Int): Unit = {
member -= i
}
}
And then I have a class which inherits the lot, overriding just one method as to call alterMember with a different value:
class mySubClass extends myBaseClass {
override def doStuff(): Unit ={
checkMember() // gives compiler error
alterMember(10) // gives compiler error AND IntelliJ says "alterMember inaccessible from this place"
}
}
checkMember() and alterMember are acting like private getters and setters. (I do only want doStuff to be able to change member , and are both inherited. WRONG - IGNORE THIS I don't understand why mySubClass is clearly able to access the private member as checkMember is just fine, but it seems it cannot alter it. Why would there be this variance? IGNORE UP TO HERE
Erasing the [this] makes no difference, but making alterMember public "fixes" it - but gives a level of access to member that I do not want.

The answer here, based on #MuratMustafin 's suggestion is to make the member and the two private methods protected.
What was also throwing, was that I needed to compile myBaseClass before attempting to compile mySubClass , otherwise it will say mySubClass cannot find those protected methods. Perhaps it's something with the Scala compiler that differs from the Java compiler in that it won't automatically know to compile them all, or compile them in order.

Related

Scala compile error: member of method parameter not visible to class method

I am getting a compile error of:
value txn is not a member of Charge
new Charge(this.txn + that.txn)
^
with the following Scala class definition:
class Charge(txn: Double = 0){
def combine(that:Charge): Charge =
new Charge(this.txn + that.txn)
}
Explicitly declaring txn as a val allows it to work:
class Charge(val txn: Double = 0){
def combine(that:Charge): Charge =
new Charge(this.txn + that.txn)
}
I thought val was assumed? Can somebody explain this? Is it a problem with my understanding of the default constructor or the scope of the method?
In scala, you can define classes in two forms, for ex.
class Charge(txn: Double) -> In this case scala compiler compiles it to java like below
public class Charge {
....
public Charge combine(Charge);
....
public Charge(double);
....
}
As you can notice in compiled java code, there is no public accessor for txn
Let's look at another variation of Charge class,
If you define like this class Charge(val txn: String), it gets compiled to below
public class Charge {
...
public double txn();
...
public Charge combine(Charge);
...
public Charge(double);
...
}
As you can see, in this case compiler generates public accessor for txn hence you are able to access that.txn when you mark it as val
case class Charge(txn: Double): This is data class for which scala generates getters, equals and toString for you.
You can compile this class
scalac Charge.scala
javap -c Charge.class
And then see what it generates
What you pass to constructor is essentially constructor parameters whose scope is limited to the constructor. If you want to make them visible from the outside, you have to declare them as vals or reassign to some other vals in the constructor body.

Protected abstract vars in Scala can be implemented public?

Could someone explain why scala would allow a public variable, to satisfy the implementation of an abstract declared Protected item? My first assumption is that the compiler would complain, but I created a small test to see if this worked, and to my surprise it does. Is there an advantage to this? (perhaps this is normal in OOP?) Any methods to avoid the accidental pitfall?
object NameConflict extends App {
abstract class A {
protected[this] var name:String
def speak = println(name)
}
class B(var name:String) extends A { //notice we've declared a public var
}
val t = new B("Tim")
t.speak
println(t.name) // name is exposed now?
}
It's normal and as in Java. Sometimes it's desirable to increase the visibility of a member.
You can't do it the other way around and turn down visibility in a subclass, because the member can by definition be accessed through the supertype.
If invoking a method has terrible consequences, keep the method private and use a template method that can be overridden; the default implementation would invoke the dangerous method.
abstract class A {
private[this] def dangerous = ???
final protected def process: Int = {
dangerous
template
}
protected def template: Int = ???
}
class B extends A {
override def template = 5
}

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.

How to implement intermediate types for implicit methods?

Assume I want to offer method foo on existing type A outside of my control. As far as I know, the canonical way to do this in Scala is implementing an implicit conversion from A to some type that implements foo. Now I basically see two options.
Define a separate, maybe even hidden class for the purpose:
protected class Fooable(a : A) {
def foo(...) = { ... }
}
implicit def a2fooable(a : A) = new Fooable(a)
Define an anonymous class inline:
implicit def a2fooable(a : A) = new { def foo(...) = { ... } }
Variant 2) is certainly less boilerplate, especially when lots of type parameters happen. On the other hand, I think it should create more overhead since (conceptually) one class per conversion is created, as opposed to one class globally in 1).
Is there a general guideline? Is there no difference, because compiler/VM get rid of the overhead of 2)?
Using a separate class is better for performance, as the alternative uses reflection.
Consider that
new { def foo(...) = { ... } }
is really
new AnyRef { def foo(...) = { ... } }
Now, AnyRef doesn't have a method foo. In Scala, this type is actually AnyRef { def foo(...): ... }, which, if you remove AnyRef, you should recognize as a structural type.
At compile time, this time can be passed back and forth, and everywhere it will be known that the method foo is callable. However, there's no structural type in the JVM, and to add an interface would require a proxy object, which would cause some problems such as breaking referential equality (ie, an object would not be equal with a structural type version of itself).
The way found around that was to use cached reflection calls for structural types.
So, if you want to use the Pimp My Library pattern for any performance-sensitive application, declare a class.
I believe 1 and 2 get compiled to the same bytecode (except for the class name that gets generated in case 2).
If Fooable exists only for you to be able to convert implicitly A to Fooable (and you're never going to directly create and use a Fooable), then I would go with option 2.
However, if you control A (meaning A is not a java library class that you can't subclass) I would consider using a trait instead of implicit conversions to add behaviour to A.
UPDATE:
I have to reconsider my answer. I would use variant 1 of your code, because variant 2 turns out to be using reflection (scala 2.8.1 on Linux).
I compiled these two versions of the same code, decompiled them to java with jd-gui and here are the results:
source code with named class
class NamedClass { def Foo : String = "foo" }
object test {
implicit def StrToFooable(a: String) = new NamedClass
def main(args: Array[String]) { println("bar".Foo) }
}
source code with anonymous class
object test {
implicit def StrToFooable(a: String) = new { def Foo : String = "foo" }
def main(args: Array[String]) { println("bar".Foo) }
}
compiled and decompiled to java with java-gui. The "named" version generates a NamedClass.class that gets decompiled to this java:
public class NamedClass
implements ScalaObject
{
public String Foo()
{
return "foo";
}
}
the anonymous generates a test$$anon$1 class that gets decompiled to the following java
public final class test$$anon$1
{
public String Foo()
{
return "foo";
}
}
so almost identical, except for the anonymous being "final" (they apparently want to make extra sure you won't get out of your way to try and subclass an anonymous class...)
however at the call site I get this java for the "named" version
public void main(String[] args)
{
Predef..MODULE$.println(StrToFooable("bar").Foo());
}
and this for the anonymous
public void main(String[] args) {
Object qual1 = StrToFooable("bar"); Object exceptionResult1 = null;
try {
exceptionResult1 = reflMethod$Method1(qual1.getClass()).invoke(qual1, new Object[0]);
Predef..MODULE$.println((String)exceptionResult1);
return;
} catch (InvocationTargetException localInvocationTargetException) {
throw localInvocationTargetException.getCause();
}
}
I googled a little and found that others have reported the same thing but I haven't found any more insight as to why this is the case.

Scala overriding a non-abstract def with a var

In Scala I can do this:
trait SomeTrait {
protected def foo: String
}
class Wibble extends SomeTrait {
protected var foo = "Hello"
}
But I cannot do the same thing where I provide a default definition for foo
trait SomeTrait {
protected def foo: String = "World"
}
class Wibble extends SomeTrait {
protected var foo = "Hello" //complains about lack of override modifier
override protected var foo = "Hello" //complains "method foo_ overrides nothing"
}
Why can't I do this?
EDIT: After a conversation on the scala-users mailing list, I have raised this in trac
In Scala, when you write a var foo, the Scala compiler automatically generates a setter (called foo_=) and a getter (called foo) for it, and sets the field as private (you'll see it as private if you decompile a class having 'public' Scala fields with javap). That's what the 'method foo_= overrides nothing' error means. In your trait you haven't defined a foo_= method, and for a public field setter and getters always come in pairs.
If you do not provide a default value in the trait (i.e. abstract method), then the override keyword is not necessary. Therefore, in your first example, the getter overrides the abstract method and the setter... it just is there. The compiler doesn't complain. But when you provide an actual implementation of the method in the trait, you need to specifically write the override keyword when overriding. When writing protected var foo, you haven't specified the override keyword for the getter and when writing override protected var foo, you have also indicated to the compiler that method foo_= is to be overridden, but the trait has no such method.
Also, logically you cannot really override a def with a var (considering a strict view of overriding, like in the previous paragraph). A def is logically a function (you give it some input, it produces an output). A var is similar to a no-arg function, but also supports setting its value to something else, an operation which is not supported by a function. Instead, if you would change it to a val, it would be OK. It's like a function that always produces the same (cached) result.
If you want to have similar behaviour to a var you could do something like this (by having explicit setter and getters):
class Wibble extends SomeTrait {
private var bar = "Hello"
override protected def foo = bar
protected def foo_=(v: String) { bar = v}
}
Now you can do anything you could do with a var :).
val x = new Wibble
println(x.foo) // yields "Hello"
x.foo = "Hello again"
println(x.foo) // yields "Hello again"