Super Powers to Qualified Access Modifiers

Scala uses access modifiers quite differently from Java. Let’s see what the differences are and why qualified access modifiers are so powerful in Scala.

default access modifier

Scala >> public
Java >> protected

While in Scala the public keyword doesn’t exist, Java allows you to explicitly use the keyword protected as you please.

private

Scala >> accessible from a class and its companion object
Java >> accessible from a class and its inner classes

 

Scala makes a special link between a class and its companion object, but not with inner classes as they are not accessible with a private modifier.

protected

Scala >> accessible from a class and its subclasses
Java >> accessible from all the classes in the same package

Scala is quite restrictive here 😐 (but don’t worry too much, keep reading…)

public

Scala and Java >> accessible from everywhere

Finally something that works in the same way! 😀

So far, we could think that the access modifier system in Scala is more limited than the Java one. Actually, it is a lot more powerful than the Java one, thanks to the super powers of qualified access modifiers!

private[X] and protected[X]

By adding qualifiers to an access modifier we can redefine its visibility. In the following definitions, X can be a package, an object or a class:

private[X] >> private and accessible from X
protected[X] >> protected and accessible from X

We can use this technique to obtain exactly the same meaning of the Java access modifiers:

– Java private member in class MyClass becomes Scala private[MyClass] member
– Java protected member in package girlcoding becomes Scala protected[girlcoding] member

private[this]

We can also declare a member as object-private:

private[this] >> accessible only for the instance that contains the definition/field

This makes sure that the member will not be visible to other objects of the same class…it’s like a super private modifier! 😀

Shared package code? Fear no more!

Sometimes code is common to all the classes of a specific package (e.g.: conversions between objects, custom logs, shared operations, etc). Our lovely Java doesn’t seem to have a convenient way of declaring code as part of a package, rather than just a class….but FEAR NO MORE! Let’s see how we can this in Scala using package objects.

First step is to define the shared package code.

// in file girlcoding/tutorial/package.scala
package girlcoding

package object tutorial {
  def customLog(msg: String) {
    println(s"Customised package log: $msg")
  }
}

The compiler will extract and compile the package code into a package.class file: the convention is to be consistent with it and to put its source code in a package.scala file as well — but you are not forced to!

We are now ready to use this shared code in all the girlcoding.tutorial classes:

// in file girlcoding/tutorial/MyClassA.scala
package girlcoding.tutorial

class MyClassA {
  def saySomething(msg: String) = customLog(msg)
}

What if we what to use it in sub packages as well?

// in file girlcoding/tutorial/whatever/MyClassB.scala
package girlcoding.tutorial
package whatever
// package girlcoding.tutorial.whatever doesn’t compile!

class MyClassB {
  def saySomethingElse(msg: String) = customLog(msg)
}

Note that if we use the declaration package girlcoding.tutorial.whatever (see line 4), it doesn’t work: to fix it, we need to declare a dependency on package girlcoding.tutorial as well (see lines 2-3).

This simple main class is checking that everything is working together as expected:

import girlcoding.tutorial.MyClassA
import girlcoding.tutorial.whatever.MyClassB

object MyMain {
  def main(args: Array[String]) {
    val myClassA = new MyClassA
    myClassA.saySomething("Hello from class A")
    // it prints: "Customised package message: Hello from class A"

    val myClassB = new MyClassB
    myClassB.saySomethingElse("Yo, I am way cooler than class A!")
     // it prints: "Customised package message: Yo, I am way cooler than class A!"
  }
}

Traits are better than Legos!

One of the most powerful (and cool) features in Scala is that you can use traits as stackable modifications.
Let’s see how it works with a simple tutorial 🙂

Our goal is to create a list of ordered colours, let’s call it ColourMixer. First we create a class to represent what a basic (empty) colour mixer is:

class ColourMixer {
   def colours: List[String] = List();
   override def toString = colours mkString ", "
}

Let’s create our Legos blocks!

trait Red extends ColourMixer { 
	abstract override def colours = "red" :: super.colours 
}

trait Green extends ColourMixer { 
	abstract override def colours = "green" :: super.colours 
}

trait Blue extends ColourMixer { 
	abstract override def colours = "blue" :: super.colours 
}

…wait a second! Are we abstracting a concrete method???
Traits are dynamically bound, while classes are statically bound: classes select a specific implementation according to the declared type, instead traits do it at runtime. Because of this property, we cannot say what implementation super is referring to — that’s why the abstract keyword is appropriate here. We will be able to decide only at runtime…and that’s why we can now play Legos!

val bgr = new ColourMixer with Red with Green with Blue
println(s"BGR: $bgr") // it prints: "BGR: blue, green, red";

val rgb = new ColourMixer with Blue with Green with Red
println(s"RGB: $rgb") // it prints: "RGB: red, green, blue"

Note that the application order is usually from the last to the first trait.

How cool is that! 😀

To Feature Branch or Not to Feature Branch?

Even when working with Agile methodologies and a Continuous Integration pipeline, some developers love feature branching – and they complain a lot when they are forbidden from using it!
The arguments in its favour are usually:
– “It makes easy to code review”
– “I can focus on my task and worry about conflicts later”
– “No feature branching means no code reviews. We will drop our code quality!”

Let’s discuss them 🙂

“It makes easy to code review”

Code reviews are essential in the team to ensure high quality and a consistent style in the code. Although it’s true that branches make easy to create pull requests, they are not the only way to review the code. I personally prefer to have a team meeting where all the commits are discussed all together face-to-face. There are several benefits in this approach:
– Misunderstandings are reduced – no more long cold threads comments arguing!
– Less experienced team members can learn from the most experienced ones.
– The team can discuss (and change if needed!) its guidelines and style when needed.

Unfortunately, there are some disadvantages as well:
– Meetings are time consuming and they need to be properly organised.
– Each developer needs to read the code to review before the meeting to build some basic understanding of it: again, discipline and time needed!

“I can focus on my task and worry about conflicts later”

Feature branching delays conflicts, doesn’t make them disappear! This is against the continuous integration methodology: it is better to discover conflicts as soon as we create them rather than on a Friday afternoon at 16.00 with the release scheduled on Monday at 11.00 (yes, it happened 😐 )

“We will drop our code quality!”

Actually, it’s the opposite! Feature branching discourages refactoring to avoid the generation of conflicts – if you ever had to deal with git conflict you know what I am talking about!