2013-06-20 3 views
2

Как в Scala я могу определить локальную переменную в основном конструкторе?Локальная переменная Scala внутри основного конструктора

Мне нужно решить это упражнение из Scala for the impatient книги:

Написать класс Person с первичным конструктором, который принимает строку , содержащую имя во-первых, пробел и фамилию, например, новый Человек («Фред Смит»). Поставлять свойства только для чтения firstName и lastName. Должен ли параметр первичного конструктора быть var, a val или простой параметр? Зачем?

И теперь мое решение выглядит следующим образом:

class Person(firstLast: String) { 
    private[this] val firstLastAsArr = firstLast.trim.split(" ") 

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

Как я могу ограничить firstLastAsArr переменную видимость основного объема конструктора (теперь есть класс сфера)?

+0

возможно дубликат [Как вы определяете локальный уаг/Вэл в основной конструктор в Scala?] (http://stackoverflow.com/ вопросы/1118669/how-do-you-define-a-local-var-val-in-the-primary-constructor-in-scala) –

ответ

5

Одно из решений заключается в инициализации firstName и lastName сразу, что позволяет превратить firstLastAsArr в локальное временное значение внутри блока инициализации:

class Person(firstLast: String) { 
    val (firstName, lastName) = { 
    val firstLastAsArr = firstLast.trim.split(" ") 
    (firstLastAsArr(0), firstLastAsArr(1)) 
    } 
} 
+0

'firstLastAsArr (1)' фактически будет содержать разделитель, то есть '' " ' –

+3

@MalteSchwerhoff whoa? '' John Doe '.trim.split ("") 'приводит к' Array (John, Doe) ' –

+0

@ om-nom-nom Интересно. Я попробовал его локально как скрипт Scala 2.10.1 (https://gist.github.com/anonymous/5821751), но http://ideone.com/4b27Dr показывает поведение, а также Scala 2.10.0. –

2

Вы не строго нужна промежуточная переменная:

class Person(firstLast: String) { 
    val (firstName, lastName) = 
    firstLast.trim.split(" ") match {case Array(first, last) => (first, last)} 
} 

Однако, если ваше преобразование от firstLast до firstName и lastName увеличивается, например, потому, что вы проверяете t шляпа есть ровно один первый и один фамилия, то я бы инкапсулировать всю расщепляющий-бизнес в выделенном методе:

class Person(firstLast: String) { 
    val (firstName, lastName) = split(firstLast) 

    private def split(firstLast: String): (String, String) = { 
    val firstLastAsArr = firstLast.trim.split(" ") 
    ... 
    (first, last) 
    } 
} 
4

Это не общий ответ, но в данном случае вы можете написать:

val Array(firstName, lastName) = firstLast.trim.split(" ") 
1

шаблона соответствие в конструкторе работает просто отлично, но вы должны рассмотреть вопрос о переходе такой логики от конструкторы к заводскому способу:

case class Person(firstName: String, lastName: String) 
object Person{ 
    def apply(firstLast: String) = { 
    val firstLastAsArr = firstLast.trim.split(" ") 
    new Person(firstLastAsArr(0), firstLastAsArr(1)) 
    } 
} 

val p = Person("My Title") 
+1

@ pagoda_5b: это действительно не правильный ответ в этом случае, но я не могу добавить комментарий для созданного кода для комментариев.Я думаю, что тот, кто должен инициализировать 2 поля из 1 конструктора, должен использовать фабричный метод. Это не о домашнем задании. – senia

+0

+1 для решения на основе фабрики - я бы тоже пошел на этот шаблон, так как он избегает создания временных кортежей. – axel22

Смежные вопросы