Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>Short answer:</strong></p> <p>As far as I can tell, the values are always accessed through the accessor method. Using <code>def</code> defines a simple method, which returns the value. Using <code>val</code> defines a <strong>private [*]</strong> final field, with an accessor method. So in terms of access, there is very little difference between the two. The difference is conceptual, <code>def</code> gets reevaluated each time, and <code>val</code> is only evaluated once. This can obviously have an impact on performance.</p> <p>[*] Java private</p> <p><strong>Long answer:</strong></p> <p>Let's take the following example:</p> <pre><code>trait ResourceDef { def id: String = "5" } trait ResourceVal { val id: String = "5" } </code></pre> <p>The <code>ResourceDef</code> &amp; <code>ResourceVal</code> produce the same code, ignoring initializers:</p> <pre><code>public interface ResourceVal extends ScalaObject { volatile void foo$ResourceVal$_setter_$id_$eq(String s); String id(); } public interface ResourceDef extends ScalaObject { String id(); } </code></pre> <p>For the subsidiary classes produced (which contain the implementation of the methods), the <code>ResourceDef</code> produces is as you would expect, noting that the method is static:</p> <pre><code>public abstract class ResourceDef$class { public static String id(ResourceDef $this) { return "5"; } public static void $init$(ResourceDef resourcedef) {} } </code></pre> <p>and for the val, we simply call the initialiser in the containing class</p> <pre><code>public abstract class ResourceVal$class { public static void $init$(ResourceVal $this) { $this.foo$ResourceVal$_setter_$id_$eq("5"); } } </code></pre> <p>When we start extending:</p> <pre><code>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 </code></pre> <p>Where we override, we get a method in the class which just does what you expect. The def is simple method:</p> <pre><code>public class ResourceDefClass implements ResourceDef, ScalaObject { public String id() { return "6"; } } </code></pre> <p>and the val defines a private field and accessor method:</p> <pre><code>public class ResourceValClass implements ResourceVal, ScalaObject { public String id() { return id; } private final String id = "6"; public String foobar() { return id(); } } </code></pre> <p>Note that even <code>foobar()</code> doesn't use the field <code>id</code>, but uses the accessor method.</p> <p>And finally, if we don't override, then we get a method which calls the static method in the trait auxiliary class:</p> <pre><code>public class ResourceNoneClass implements ResourceDef, ScalaObject { public volatile String id() { return ResourceDef$class.id(this); } } </code></pre> <p>I've cut out the constructors in these examples.</p> <p>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.</p> <p><strong>Even longer answer:</strong></p> <p>Josh Suereth did a very interesting talk on <a href="http://skillsmatter.com/podcast/scala/binary-resilience" rel="noreferrer">Binary Resilience at Scala Days 2012</a>, which covers the background to this question. The abstract for this is:</p> <blockquote> <p>This talk focuses on binary compatibility on the JVM and what it means to be binary compatible. An outline of the machinations of binary <em>incompatibility</em> 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 <em>resilient</em>.</p> <p>In particular, this talk looks at:</p> <ul> <li>Traits and binary compatibility</li> <li>Java Serialization and anonymous classes</li> <li>The hidden creations of lazy vals</li> <li>Developing code that is binary resilient</li> </ul> </blockquote>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload