This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Re: Constructor arguments and fields with the same name

4 replies
David Pollak
Joined: 2008-12-16,
User offline. Last seen 42 years 45 weeks ago.

By default, the named constructor parameters are private assign-once variables and may be accessed by any method in the class.

If you want the constructor parameter to be publicly accessable:
class MyClass(var name: String)

On Jan 10, 2009 6:06 PM, "Chris Lambrou" <chris [at] lambrou [dot] net> wrote:

I'm fairly new to Scala, having come from a Java and C# background, and I have a question regarding name clashes between fields and constructor arguments. Consider the fairly common naming convention, shown in this simple java example:

public class MyClass {
  public String name;

  public MyClass(String name) {
    this.name = name;
  }
}

I'd like to be able to do the equivalent in a Scala class, a bit like the following, but am not sure how to do so correctly, or even if it's possible:

class MyClass(name: String) {
  val name: String = name   // Clearly nonsense.
}

I realise that there's no need to do this for case classes, since the constructor arguments are automatically exposed as public fields, but how can I do this for non-case classes? So far, I've been having to come up with two names for everything - one for the field and one for the constructor argument - which is a pain and can produce overly confusing code. I've been looking for an example of this in the Programming in Scala book, but this scenario seems to be inconveniently avoided, unfortunately.

Any help or advice would be much appreciated.

Chris

Ricky Clarkson
Joined: 2008-12-19,
User offline. Last seen 3 years 2 weeks ago.
Re: Constructor arguments and fields with the same name
and if you want them to be publically accessible but immutable:
class MyClass(val name: String)

2009/1/11 David Pollak <feeder [dot] of [dot] the [dot] bears [at] gmail [dot] com>

By default, the named constructor parameters are private assign-once variables and may be accessed by any method in the class.

If you want the constructor parameter to be publicly accessable:
class MyClass(var name: String)

On Jan 10, 2009 6:06 PM, "Chris Lambrou" <chris [at] lambrou [dot] net> wrote:

I'm fairly new to Scala, having come from a Java and C# background, and I have a question regarding name clashes between fields and constructor arguments. Consider the fairly common naming convention, shown in this simple java example:

public class MyClass {
  public String name;

  public MyClass(String name) {
    this.name = name;
  }
}

I'd like to be able to do the equivalent in a Scala class, a bit like the following, but am not sure how to do so correctly, or even if it's possible:

class MyClass(name: String) {
  val name: String = name   // Clearly nonsense.
}

I realise that there's no need to do this for case classes, since the constructor arguments are automatically exposed as public fields, but how can I do this for non-case classes? So far, I've been having to come up with two names for everything - one for the field and one for the constructor argument - which is a pain and can produce overly confusing code. I've been looking for an example of this in the Programming in Scala book, but this scenario seems to be inconveniently avoided, unfortunately.

Any help or advice would be much appreciated.

Chris

Chris Lambrou
Joined: 2009-01-11,
User offline. Last seen 42 years 45 weeks ago.
Re: Constructor arguments and fields with the same name
Thanks for all of the prompt replies. I knew that the constructor arguments were available to privately ot methods in the class, but I assumed that it was because referencing them simply created a closure. I hadn't realised that they could be made publicly available simply by adding a val or var prefix. This leads me to a couple of further questions which I hope someone can also shed light on.


First question - If I add a val or var prefix to the constructor arguments, so that they are available as public fields, how should I write scaladoc comments for them? It seems that the@param comment of the constructor isn't as expressive as a self-contained /**...*/ comment for a public field.


Second question - In my original message, I've actually oversimplified the problem. What I'd really like to achieve is something a bit more like the following, where the value of the constructor argument is not directly exposed as a public field, but is actually modified first:

In Java:
public class MyClass {
  public String path;

  public MyClass(String path) {
    this.path = SomeHelperClass.normalise(path);
  }
}

In Scala:
class MyClass(path: String) {
  val path: String = SomeHelperObject.normalise(path)  // Again, this won't work.
}

This scenario occurs far less frequently than simply exposing a constructor argument as a public field. So, if there's no solution to this, I'm okay with using different names for the constructor argument and public fields, but it would be nice if the same name could somehow be used for both.


Thanks once again,

Chris
Bill Venners
Joined: 2008-12-18,
User offline. Last seen 31 weeks 5 days ago.
Re: Constructor arguments and fields with the same name

Hi Chris,

On Sat, Jan 10, 2009 at 7:07 PM, Chris Lambrou wrote:
> Thanks for all of the prompt replies. I knew that the constructor arguments
> were available to privately ot methods in the class, but I assumed that it
> was because referencing them simply created a closure. I hadn't realised
> that they could be made publicly available simply by adding a val or var
> prefix. This leads me to a couple of further questions which I hope someone
> can also shed light on.
>
>
> First question - If I add a val or var prefix to the constructor arguments,
> so that they are available as public fields, how should I write scaladoc
> comments for them? It seems that the@param comment of the constructor isn't
> as expressive as a self-contained /**...*/ comment for a public field.
>
I just use @param in the doc comment for the class. Scala calls these
things "class parameters," so conceptually their doc comments kind of
belong there anyway.

>
> Second question - In my original message, I've actually oversimplified the
> problem. What I'd really like to achieve is something a bit more like the
> following, where the value of the constructor argument is not directly
> exposed as a public field, but is actually modified first:
>
> In Java:
> public class MyClass {
> public String path;
>
> public MyClass(String path) {
> this.path = SomeHelperClass.normalise(path);
> }
> }
>
> In Scala:
> class MyClass(path: String) {
> val path: String = SomeHelperObject.normalise(path) // Again, this won't
> work.
> }
>
> This scenario occurs far less frequently than simply exposing a constructor
> argument as a public field. So, if there's no solution to this, I'm okay
> with using different names for the constructor argument and public fields,
> but it would be nice if the same name could somehow be used for both.
>
You do have to use two different names in that case, and I don't think
we've ever much discussed good naming conventions for those. Martin
Odersky suggested when we were working on the book that you use a more
descriptive name for the field, because he expected the field name
would show up more in code. We had this issue in the Stairway book in
the Rational class. We used n and d for parameter names, and numer and
denom for field names. I don't like one-char names for most things,
including this example, but one reason they show up in the book is to
help the code examples fit on a page. I've seen some people put
underscores in one or the other name, but I don't quite like that
approach. I think both the parameter and field names should be
self-explanatory, and would normally follow Martin's suggestion of
giving the "better" name to the fields.

Bill

James Iry
Joined: 2008-08-19,
User offline. Last seen 1 year 23 weeks ago.
Re: Constructor arguments and fields with the same name
There are two common solutions to that

Solution 1 is to use another name.  I often prepend with an underscore to remind myself that the parameter is supposed to have limited scope

class MyClass(_path : String) {
   val path = SomeHelperObject.normalize(_path)
}

Solution 2 is to move construction responsibilities to a companion object


object MyClass {
   def apply(path : String) = new MyClass(SomeHelperObject.normalize(path))
}

class MyClass private(val path : String)


On Sat, Jan 10, 2009 at 7:07 PM, Chris Lambrou <chris [at] lambrou [dot] net> wrote:

In Java:
public class MyClass {
  public String path;

  public MyClass(String path) {
    this.path = SomeHelperClass.normalise(path);
  }
}

In Scala:
class MyClass(path: String) {
  val path: String = SomeHelperObject.normalise(path)  // Again, this won't work.
}

This scenario occurs far less frequently than simply exposing a constructor argument as a public field. So, if there's no solution to this, I'm okay with using different names for the constructor argument and public fields, but it would be nice if the same name could somehow be used for both.


Thanks once again,

Chris

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland