Используйте переменные класса как константы в Scala

Я работаю над изучением Scala, имея опыт работы с C++. Я пытаюсь написать небольшой класс для приложения для отслеживания задач, которое я взламываю вместе, чтобы помочь мне научиться кодировать Scala.

Кажется, что это должно быть просто, но по какой-то причине это ускользает от меня:

package com.catenacci.tts

class Task(val ID:Int, val Description:String) {
 val EmptyID = 0
 val EmptyDescription = "No Description"

 def this() = this(EmptyID,EmptyDescription)
 def this(ID:Int)={
   this(ID,EmptyDescription)
 }
 def this(Description:String)={
   this(EmptyID,Description)
 }
}

Я пытаюсь предоставить три конструктора: Task(ID, Description), Task(ID), Task(Description). В последних двух случаях я хочу инициализировать значения постоянными значениями, если одно из значений не предоставлено вызывающим абонентом. И я хочу иметь возможность проверить это вне класса для целей модульного тестирования. Поэтому я решил, что добавление двух публичных переменных позволит мне проверять извне класса, чтобы убедиться, что мое состояние соответствует ожиданию.

Однако по какой-то причине этот код не скомпилируется. Я получаю следующую ошибку:

error: not found: value EmptyID

и

error: not found: value EmptyDescription

Итак, что мне не хватает? Я работаю над «Программированием на Scala», поэтому, если есть простой ответ на этот вопрос, пожалуйста, дайте мне номера страниц. Я не против прочитать, но, взглянув на код на странице 60 и странице 62, я не понимаю, почему этот код не работает.

Я предполагаю, что это как-то связано с тем, что это методы конструктора и, возможно, два vals не инициализируются до конца конструкторов. Если это так, есть ли способ получить эффект, который я ищу?


person Onorio Catenacci    schedule 29.04.2009    source источник
comment
См. также SIP 23 или 42.type: stackoverflow.com/a/39065260/6309   -  person VonC    schedule 21.08.2016


Ответы (3)


Вы можете определить константы в объекте-компаньоне:

object Task { 
 val EmptyID = 0
 val EmptyDescription = "No Description"
}

А затем укажите их как Task.EmptyID и Task.EmptyDescription.

Я думаю, что Scala 2.8 поддерживает значения по умолчанию.

person Germán    schedule 29.04.2009

См. Герман для ответа. Это происходит потому, что конструктор технически является частью статической области видимости. Другими словами, конструктор не может получить доступ ни к одному члену экземпляра, поскольку экземпляр еще не создан. Любые «члены класса» на самом деле являются членами экземпляра, поэтому код в вопросе не работает. Ответ Германа исправляет это, перемещая два соответствующих значения в объект-компаньон, что фактически делает их статическими членами класса Task (на самом деле это не так, но вы можете думать об этом таким образом).

person Daniel Spiewak    schedule 29.04.2009
comment
Спасибо - приятно знать, почему это не сработало, а также знать, как это исправить. - person Onorio Catenacci; 30.04.2009
comment
Ага. Некоторое время мне было интересно, почему это не было проблемой в Java с классическим общедоступным статическим финалом - это из-за статического. - person Germán; 30.04.2009

В разделе «Программирование на Scala» см. раздел 6.7, где объясняется цепочка вызовов конструктора. Первичный конструктор описывается как «единственная точка входа класса».

person Don Mackenzie    schedule 03.05.2009