Wednesday, April 16, 2008

Instance read-only access modifier

Be it in C++, Java, or Scala, I have always been bothered by the fact that an instance of a class has access to the private members of another instance.

Sure, it's mighty useful for copy constructors and other functionalities like adding, but I always felt there should also be a "private read-only" access modifier.

Of course, there is no problem in the case of immutable objects. Here's a Scala example (using Scala version 2.6.1).

class Domino(p: int) {
private val points=p

def add(that: Domino) = new Domino(p + that.points)

override def toString() = "Domino: points=[" + points +"]"
}

scala> val d1 = new Domino(1)
d1: Domino = Domino: points=[1]

scala> val d3 = new Domino(3)
d3: Domino = Domino: points=[3]

scala> d1.add(d3)
res2: Domino = Domino: points=[4]


But what if, for whatever reason, I am using mutable objects?

In the following code, I have no quarrel with the function addToMe, but I am bothered by the function addToOther. I wish I could specify my special "private read-only" access modifier there, so this function would not compile.

Normal Scala code:

class MutableDomino(p: int) {
private var points=p

def addToMe(that: MutableDomino) = { points = points + that.points }

def addToOther(that: MutableDomino) { that.points = that.points + points }

override def toString() = "MutableDomino: points=[" + points +"]"
}


I would like to be able to write the class like the following (the exact name of the access modifier is not important)

Crazy Scala code:

class MutableDomino(p: int) {
private[this] var points=p

def addToMe(that: MutableDomino) = { points = points + that.points }

def addToOther(that: MutableDomino) { that.points = that.points + points }

override def toString() = "MutableDomino: points=[" + points +"]"
}


What do you think about an instance read-only access modifier?

Is it useful, or is it over the edge?

Post update!

Thanks to Eric's heads up below, I learned about the access modifier.

I can actually go even further than prevent write-access to a private member of another instance: I can block read and write access to it altogether using the "this" qualifier.
E.g. : private[this]

Here is a new version of the MutableDomino class with it that will be, rightly so, rejected by the Scala interpreter:

class MutableDomino(p: int) {
private var points=p

def addToMe(that: MutableDomino) = { points = points + that.points }

def addToOther(that: MutableDomino) { that.points = that.points + points }

override def toString() = "MutableDomino: points=[" + points +"]"
}

error: value points is not a member of MutableDomino
def addToMe(that: MutableDomino) = { points = points + that.points }
^
error: value points is not a member of MutableDomino
def addToOther(that: MutableDomino) { that.points = that.points + points }