Class parameters are not necessarily class members. You can have class parameters that do not become class members.
Method 1
class Foo(bar0: String) {
val bar = bar0.toLowerCase()
}
@main
def main(): Unit = {
println(Foo("AsDfGh").bar)
}
prints:
asdfgh
and the decompiled code is:
public class Foo {
private final String bar;
public Foo(final String bar0) {
this.bar = bar0.toLowerCase();
}
public String bar() {
return this.bar;
}
}
You see, bar0
is a "temporary" value, it does not become a field because it is not referenced.
So if you want to change a value, just do not use the original value in the methods.
Method 2
For case classes, it does not seem to work in 2022, but here is another trick:
case class Point (x: Double, y: Double)
class PolarPoint(r: Double, alpha: Double) extends Point(r*Math.cos(alpha), r*Math.sin(alpha))
Here r
and alpha
do not become members of PolarPoint
.
If you don't need two types, you can make the 1st constructor protected
:
case class Foo protected(x:Int)
class FooImpl(x0:Int) extends Foo(myFunc(x0))
You will reference objects as Foo
s but create FooImpl
s.
Method 3
Your class can have multiple parameter lists and implicit
s:
class Qux(x:String)(implicit val y:String = x.toLowerCase())
is converted to:
public class Qux {
private final String y;
public static String $lessinit$greater$default$2(String var0) {
return Qux$.MODULE$.$lessinit$greater$default$2(var0);
}
public Qux(final String x, final String y) {
this.y = y;
}
public String y() {
return this.y;
}
}
You see that here only y
becomes a field.