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 }

4 comments:

Eric said...

Hello, and congratulations for your new blog.

I have good news for you! In Scala, you can use the "private[this]" declaration that will hide the private member from any other instance.

I can recommend the Artima book on Scala for a nice presentation of the access modifiers in Scala, you'll see that it's a huge improvement over Java.

Eric.

The Careful Programmer said...

Hello Eric,

Thank you so much for your feedback.

It's a bit embarrassing that my first post is a wish for a feature that already exists!

The funniest thing is that I did buy the book programming in Scala, but I've been reading it in whimsical order and I skipped that part.

I'll give it a thourough, chronological read when I get the printed version 8)

Lemmy said...

I don't see this as an important feature really. I use private so other people (or I as a user of another class) can not mess with my internal state, because my current mindset should not revolve around the internals of that class.

But while I am working on that particular class I have to understand things anyway, so I don't see how this helps.

The Careful Programmer said...

Hi Lemmy.

Yes, one way of seeing private access is using it exactly like you're describing.

On the other hand, there is also a security concern of what should be accessible from one instance of an object an another.

I've got two concern. The first is what I explored in the article: I do not like an instance modifying the private variables of another instance.

My other example is less easy to define. I haven't explored that avenue that much, it's more of an intuition.

As an example, imagine an instance of an object representing a credit card transaction. Shouldn't the credit card number be private to other transaction instances?