Последний код компилируется и завершается с ошибкой только в время выполнения - то, что вы видите, является исключением, а не ошибкой компилятора.None
наследуется от Option
и поэтому должно определять метод get
.
РЕДАКТИРОВАТЬ: вопрос можно перефразировать как «почему компилятор принимает явно глупый вызов None.get
?».На этот вопрос действительно нетривиально ответить, поэтому я потрачу еще несколько слов на разных уровнях.
- Сначала уточнение: чтобы понять разницу между ошибками во время компиляции и во время выполнения,Вероятно, полезно создать программу Scala, содержащую код, который вы хотите протестировать, скомпилировать и протестировать его.Если вы запускаете код только по приглашению, начинающему становится сложнее оценить разницу между ошибкой времени компиляции и ошибкой времени выполнения.Тем не менее, опытный пользователь научится распознавать другой формат ошибок.
- Разве метод не похож на
get
глупый, так как он может дать сбой во время выполнения? Действительно, когда выиметь значение v
типа Option[T]
, вы обычно должны использовать сопоставление с шаблоном или использовать такие методы, как getOrElse
, map
и т. д.: методы, которые работают, даже если v
пусто.Но иногда у вас есть такое значение и вы уже уверены, что v
должно быть Some(q)
: get следует использовать только тогда. - Почему, учитывая определение None, компилятор не может датьошибка времени компиляции? Компилятор выдает ошибку при вызове метода, который не определен в объекте-получателе, но
get
определен в классе Option
и, следовательно, в его двух подклассах, Some
и None
.Только его тело содержит призыв к ошибке. - Почему имеют смысл определенные определения
Option
? Для того, чтобы пользователь вызывался для вызова get
, когда он хочетк, это должно быть определено на Option
.В противном случае перед вызовом нужно будет выполнить приведение типа - в этот момент будет проще выполнить сопоставление с шаблоном. - Почему компилятор до сих пор не распознает, что код выполняетсяпотерпеть неудачу во время выполнения? Потому что распознать нетривиальные случаи сложно.Например, в функции, которую вы разместили выше, неясно, будет ли когда-либо выполняться
None.get
;более того, код, который вы дали, выдаст ошибку во время выполнения, если вы передадите пустой список;поэтому это правильная реализация обычной спецификации последней.В общем, у вас может быть v get
, и может быть нетривиально понять, может ли v
быть или не быть None
.Существуют и другие инструменты, которые пытаются найти ошибки такого рода (пока не уверены, есть ли они в Scala), но они также имеют тенденцию давать либо ложные отрицательные, либо ложные положительные результаты: они могут сообщать о проблемах, которые не могут возникнуть, или пропустить соответствующие проблемы.В конце концов, вы действительно не хотите, чтобы их выходные данные были вместе с выходными данными компилятора Scala.Выполнение некоторых простых простых проверок в компиляторе может иметь смысл, но у вас есть технический вопрос: неясно, стоит ли дополнительный код своей стоимости.