Как вернуть 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 без несоответствия типа.