This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 4.7, “How to prevent getter and setter methods from being generated in Scala classes.”
Problem
When you define a class field as a var
, Scala automatically generates getter and setter methods for the field, and defining a field as a val
automatically generates a getter method, but you don’t want either a getter or setter.
Solution
Define the field with the private
or private[this]
access modifiers, as shown with the currentPrice
field in this example:
class Stock { // getter and setter methods are generated var delayedPrice: Double = _ // keep this field hidden from other classes private var currentPrice: Double = _ }
When you compile this class with scalac
, and then disassemble it with javap
, you’ll see this interface:
// Compiled from "Stock.scala" public class Stock extends java.lang.Object implements scala.ScalaObject{ public double delayedPrice(); public void delayedPrice_$eq(double); public Stock(); }
This shows that getter and setter methods are defined for the delayedPrice
field, and there are no getter or setter methods for the currentPrice
field, as desired.
Discussion
Defining a field as private
limits the field so it’s only available to instances of the same class, in this case instances of the Stock
class. To be clear, any instance of a Stock
class can access a private field of any other Stock
instance.
As an example, the following code yields true
when the Driver
object is run, because the isHigher
method in the Stock
class can access the price
field both (a) in its object, and (b) in the other Stock
object it’s being compared to:
class Stock { // a private field can be seen by any Stock instance private var price: Double = _ def setPrice(p: Double) { price = p } def isHigher(that: Stock): Boolean = this.price > that.price } object Driver extends App { val s1 = new Stock s1.setPrice(20) val s2 = new Stock s2.setPrice(100) println(s2.isHigher(s1)) }
Object-private fields
Defining a field as private[this]
takes this privacy a step further, and makes the field object-private, which means that it can only be accessed from the object that contains it. Unlike private
, the field can’t also be accessed by other instances of the same type, making it more private than the plain private
setting.
This is demonstrated in the following example, where changing private
to private[this]
in the Stock
class no longer lets the isHigher
method compile:
class Stock { // a private[this] var is object-private, and can only be seen // by the current instance private[this] var price: Double = _ def setPrice(p: Double) { price = p } // error: this method won't compile because price is now object-private def isHigher(that: Stock): Boolean = this.price > that.price }
Attempting to compile this class generates the following error:
Stock.scala:5: error: value price is not a member of Stock def isHigher(that: Stock): Boolean = this.price > that.price ^ one error found
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |