Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructor-local variables in Scala

Tags:

scala

I'm on exercise 5.7 of "Scala for the Impatient", where i need to create a class Person that takes a name:String on constructor and has 2 properties firstName and lastName filled from name split by whitespace. My first trial was :

class Person(name:String) {
  private val nameParts = name.split(" ")

  val firstName = nameParts(0)
  val lastName = nameParts(1)
}

The problem is, that now nameParts remains as a private field always visible within the class, when in fact should only exist within the constructor's local environment. The Java equivalent of what I want would be:

 class Person{
    private final String firstName;
    private final String lastName;

    Person(String name){
        final String[] nameParts = name.split(" ");
        firstName = nameParts[0];
        lastName = nameParts[1];
    }
 }

Here, nameParts exists only withing the constructor, which is what i'm aiming for. Any hints on how this can be done in Scala?

NOTE: I ended up finding a more "Scalesque" way:

class Person(name:String) {
    val firstName::lastName::_ = name.split(" ").toList 
}

but I still would like to get an answer to my question.

like image 778
Chirlo Avatar asked Apr 15 '12 13:04

Chirlo


People also ask

Does Scala have constructor?

Scala ConstructorThere are two types of constructor in Scala – Primary and Auxiliary. Not a special method, a constructor is different in Scala than in Java constructors. The class' body is the primary constructor and the parameter list follows the class name. The following, then, is the default primary constructor.

What is type constructor in Scala?

You can use certain types (like Int or String ) using literals ( 1 or 2 for Int or "James" for String ). Type constructors are types that need other types to be built. List or Option won't be a fully qualified type unless you pass another type to them (i.e. List[Int] or Option[String]

Can Scala object have constructor?

Constructors in Scala describe special methods used to initialize objects. When an object of that class needs to be created, it calls the constructor of the class. It can be used to set initial or default values for object attributes.

What is primary and auxiliary constructor in Scala?

The auxiliary constructor in Scala is used for constructor overloading and defined as a method using this name. The auxiliary constructor must call either previously defined auxiliary constructor or primary constructor in the first line of its body.


2 Answers

There is a way to avoid the private val. Just use the extractor of Array:

class Person(name: String) {
  val Array(first, last) = name.split(" ")
}

edit:

What you want to do can be achieved through a factory method on the companion and a default constructor that takes first and last as param:

class Person(val first: String, val last: String)

object Person {
  def apply(name: String) = {
    val splitted = name.split(" ")
    new Person(splitted(0), splitted(1))
  }
}

scala> Person("Foo Bar")
res6: Person = Person@37e79b10

scala> res6.first 
res7: String = Foo

scala> res6.last
res8: String = Bar

But for this simple case I would prefer my first suggestion.

The example in your link would also work, but it's kind of the same as my first example. Afaik there is no way to create a temporary variable in the constructor.

like image 167
drexin Avatar answered Oct 16 '22 23:10

drexin


What I had in mind was simply

class Person(n: String) {
  val firstName = n.split(" ")(0)
  val lastName = n.split(" ")(1)
}

If you want to factor out the common code, then drexin's answer with the array is very nice. But it requires knowledge that the reader wouldn't have had in chapter 5. However, var with tuples was covered in chapter 4, so the following is within reach:

class Person(n: String) {
  val (firstName, lastName) = { val ns = n.split(" "); (ns(0), ns(1)) }
}
like image 31
cayhorstmann Avatar answered Oct 16 '22 21:10

cayhorstmann