Как вернуть null из общей функции в Scala?
Я пишу свою собственную простую реализацию javax.sql.DataSource
, единственный способ, которым я должен работать, - это getConnection: Connection
, но интерфейс наследует многие другие методы (которые мне не нужны) от javax.sql.CommonDataSource
и java.sql.Wrapper
. Таким образом, я хотел бы "реализовать" эти ненужные методы таким образом, чтобы они на самом деле не работали, но будут вести себя адекватно при вызове. Например, я реализую boolean isWrapperFor(Class<?> iface)
как
def isWrapperFor(iface: Class[_]): Boolean = false
и я хотел бы реализовать <T> T unwrap(Class<T> iface)
как
def unwrap[T](iface: Class[T]): T = null
Но последнее не работает: несоответствие типов отчетов компилятора.
Будет ли правильным использовать null.asInstanceOf[T]
или есть лучший способ? Конечно, я рассматриваю просто бросать UnsupportedOperationException
вместо этого в этом конкретном случае, но IMHO вопрос может быть интересным.
Ответы
Ответ 1
Это связано с тем, что T
может быть типом с нулевым значением. Он работает, когда вы применяете T
к типу с нулевым значением:
def unwrap[T >: Null](iface: Class[T]): T = null
unwrap(classOf[String]) // compiles
unwrap(classOf[Int]) // does not compile, because Int is not nullable
Ответ 2
"Правильное" решение - это сделать что-то, что немедленно потерпит неудачу. Например:
def unwrap[T](iface: Class[T]): T = sys.error("unimplemented")
В scala 2.10 это было бы реализовано как:
def unwrap[T](iface: Class[T]): T = ???
Потому что в Predef
есть новый метод ???
. Это работает, потому что выражение формы throw new Exception
имеет тип Nothing
, который является подтипом любого типа (он называется дном в кругах типа теорема).
Причина, по которой это правильно, заключается в том, что гораздо лучше сбой немедленно с ошибкой, а не использование null
, которое может завершиться неудачно и обмануть причину.
Ответ 3
Как сказано в комментариях, это решение не работает
Если я правильно понял вашу проблему, вы также можете назначить значения по умолчанию, как подробно описано в что означает назначение "_" в поле в scala?. Вы можете найти дополнительную информацию в 4.2. Объявления переменных и определения Язык Scala
Спецификация
Итак, вы можете просто сделать:
def unwrap[T](iface: Class[T]): T = _
который установит unwrap
с null
без несоответствия типа.