1

Is it possible to have constructor parameters that don't become fields? For example,

class Foo(p1: String, p2: Int) {
    val f1 = p1 * p2
}

The only field I want is f1, not p1 and p2. The idea is to derive fields from parameters.

3 Answers 3

3

This is good as it is - both p1 and p2 aren't fields here, just f1. Making them fields is opt-in rather than opt-out (except for case classes, where all parameters are also fields, and you can't do anything about it).

To make them fields, you'd have to add var or val, something like

class Foo(val p1: String, var p2: Int)

EDIT: In case you want a field with the same name as a parameter but a different type or something, you can do something like this:

class Foo(p1: String, val p2: Int) {
  //Can be val if you want
  var _p1: Int = (p1 : String).toInt
  def p1: Int = _p1
  def p1_=(p1: Int) = _p1 = p1 //An optional setter
}

This is practically the same as having a field called p1.

If you also want to set fields using some complex operations and use local variables, you can use blocks (and maybe an auxiliary constructor)

class Foo(p1: String, val p2: Int) {
  val _p1: Int = {
    val intermediateVariable: String = p1
    intermediateVariable.toInt
  }
  def p1: Int = _p1

or

class Foo(val p1: Int) {

  def this(p1: String) = this({
    val uselessIntermediateVariable = p1.toInt
    uselessIntermediateVariable
  })
}
Sign up to request clarification or add additional context in comments.

4 Comments

Haha, you are right. I misremembered. I thought they default to val. A related question: is it possible to have both a non-field parameter and a filed with the same name?
What is p1_ for?
Cool. One step further, possible to have temp variables that don't become field used in the process of deriving fields from parameters?
It doesn't work in my case but I discovered apply.
2

In a simple class, if you don't add any modifier as val or var, the parameters of the constructor are private elements. Example:

class C(val a: Int, b: Int) {
  val c = a + b
}

val i = new C(1,2)

println(i.a) // it's public 
println(i.b) // this line won't allow you to compile, it's private
println(i.c) // also public

The exception is made is you make a case class, with case modifier all the parameters of the constructor will be public. You can make them private marking as private the parameter. Example:

case class C(a: Int, private val b: Int) {
  val c = a + b
}

val i = new C(1,2)

println(i.a) // it's public 
println(i.b) // this line won't allow you to compile, it's private
println(i.c) // also public

2 Comments

Now I see why I misremembered. I confused case class constructor with class constructor.
In the first case b isn't private, it isn't stored at all.
2

Just to clarify the existing answers, non-case class parameters can automatically become fields, but only if they are used in methods or lazy val initializers, e.g.

class Foo(p1: String, p2: Int) {
    val f1 = p1 * p2
    def m1() = p1 + p1
}

will make p1 a field. There's no way to avoid it other than not using them in such a way.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.