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.
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.
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]
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.
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.
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.
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)) }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With