Programming  /  Scala September 06, 2010

Learning Scala part nine – Uniform Access

In this part of the Learning Scala series we’ll take a quick look at what the Uniform Access Principle is and how Scala implements it. In the process we’ll also learn about how vals and vars are implemented behind the scenes.

The Uniform Access Principle

As many other principles and wisdoms in the world of programming the Uniform Access Principle was first published by Bertrand Meyer in Object-Oriented Software Construction. It states that "All services offered by a module should be available through a uniform notation, which does not betray whether they are implemented through storage or through computation.” In practice this means that the notation used to access a feature of a class shouldn’t differ depending on whether it’s an attribute or a method.

Java and C# (disregarding C#’s properties) does not follow the Uniform Access Principle as a field named bar of an object foo is accessed using one notation (foo.bar) while a method named bar is accessed with another notation (foo.bar()).

In Scala however both a method named bar and an attribute (a val or a var) named bar can be accessed using the same notation, foo.bar.

How vals and vars are accessed

Let’s take a look at a simple class, Person, with a single member, name.

class Person {
    val name = "Johh Doe"
}

So far throughout this series I’ve been referring to members such as Person.name as fields. While it’s convenient to think of them that way when coming from Java or C# that’s actually not accurate. In reality the Scala compiler will create a private field with a different name for storing the value and a method for accessing that value.

If we compile the above code and then decompile it using a Java decompiler such as JD-GUI to look at how the same class could (sort of) look in Java we see just this, a private field for storage and a public method for accessing its value.

public class Person
  implements ScalaObject
{
  private final String name = "Johh Doe";

  public String name() { 
    return this.name;
  }
}

If we would turn the name member into a var we’d also find a public method for setting the value of the backing field.

public class Person
  implements ScalaObject
{
  private String name = "Johh Doe";

  public String name() { return this.name; } 
  
  public void name_$eq(String paramString) { 
    this.name = paramString;
  }
}

Method, val or var, they are all accessed the same way

Thanks to how vals and vars are implemented and the fact that methods that don’t have any parameters can be called without parentheses Scala follows the Uniform Access Principle. To illustrate this, let’s look at a script that defines the Person class and prints the name member:

class Person {
    val name = "Johh Doe"
}

val john = new Person
println(john.name)

Now, let’s say that we wanted to turn the name member into a method instead. We could do so without having to change the code that uses it.

class Person {
    def name = "Johh" + " " + "Doe"
}

val john = new Person
println(john.name)

This way, as vals and vars are accessed the same way as methods we get information hiding without having to create getters and setters that pretty much always work the same way.

Another cool thing about this is that a parent class may define a parameterless method and a subclass may override that with a val. The below script illustrates this.

abstract class Person {
    def name: String
    
    def printName() = println(name)
}

class John extends Person {
    val name = "John Doe"
}

val person = new John
person.printName

Setters

So far we’ve primarily looked at vals, but how do we handle going from having a member implemented as a var to having it implemented with methods? That is, how do we create the setter? First, let’s look at an example of a class with a var:

class Person {
  var name = ""
}

val john = new Person
john.name = "John Doe"
println(john.name)

If we wanted to change the implementation of the name member from a var to methods we would have to provide both a getter and a setter. The getter should be named name, just as when we looked at vals before and the setter should be named name_=. That is the name of the var plus an underscore and an equals sign. Our example script with the name member implemented with methods instead looks like this:

class Person {
    private var privateName = ""
    
    def name = privateName
    
    def name_=(value: String) = privateName = value
}

val john = new Person
john.name = "John Doe"
println(john.name)
Note that the private var that we use for storing the value has a different name. This is necessary as fields (or whatever we want to call vals and vars) and methods are kept in the same namespace.

Recap and a look at what’s next

Coming from C# that has the concept of properties which are (in many respects) indistinguishable from public fields to clients and that can be automatically implemented by the compiler (public string MyProperty { get; set; }) the concepts discussed in this part isn’t exactly mind blowing. However, I think Scala’s implementation is much more elegant as it doesn’t require a whole separate concept in the language. There’s just fields and methods.

In the next part we’ll (finally ?) get to look at some of Scala’s functional programming features as we look at pattern matching.

About this post and the Learning Scala series

This post is a part of a series of posts in which I describe my experiences while trying to learn Scala. I try to do it in the form of a tutorial as I find doing so is an excellent way of consolidating knowledge and hopefully I can also help others. However, keep in mind that I’m in no way an expert on Scala. This is just a way to document what I’ve learned so far and there might be some things that I’ve misunderstood. If you’ve found such a thing and would like to help me correct that misunderstanding, or if you would like to leave any other kind of feedback don’t hesitate to leave a comment!

You can find links to all posts in this series at the bottom of the first post.

PS. For updates about new posts, sites I find useful and the occasional rant you can follow me on Twitter. You are also most welcome to subscribe to the RSS-feed.

Joel Abrahamsson

Joel Abrahamsson

I'm a passionate web developer and systems architect living in Stockholm, Sweden. I work as CTO for a large media site and enjoy developing with all technologies, especially .NET, Node.js, and ElasticSearch. Read more

Comments

comments powered by Disqus

More about Scala