Вопрос по generics – Как вернуть null из универсальной функции в Scala?

12

Я пишу свой простойjavax.sql.DataSource реализация, единственный способ этого мне нужно работатьgetConnection: Connection, но интерфейс наследует многие другие методы (которые мне не нужны) отjavax.sql.CommonDataSource а такжеjava.sql.Wrapper, Итак, я бы хотел "внедрить" эти ненужные методы, которые они на самом деле не будут работать, но будут вести себя адекватно при вызове. Например я реализуюboolean isWrapperFor(Class<?> iface) как

<code>def isWrapperFor(iface: Class[_]): Boolean = false
</code>

и я хотел бы реализовать<T> T unwrap(Class<T> iface) как

<code>def unwrap[T](iface: Class[T]): T = null
</code>

Но последнее не работает: компилятор сообщает о несоответствии типов.

Будет ли правильно использоватьnull.asInstanceOf[T] или есть лучший способ? Конечно, я считаю, просто бросатьUnsupportedOperationException вместо этого в данном конкретном случае, но ИМХО вопрос все еще может быть интересным.

Ваш Ответ

3   ответа
6

& Quot; правильно & quot; Решение состоит в том, чтобы сделать что-то, что будетimmediately потерпеть поражение. Вот так:

def unwrap[T](iface: Class[T]): T = sys.

В скале2.10, это было бы реализовано как:

def unwrap[T](iface: Class[T]): T = ???

Потому что есть новый метод вPredef называется???, Это работает, потому что выражение формыthrow new Exception имеет типNothing, который является подтипом любого типа (он называетсяbottom в теоретико-типовых кругах).

Причина в том, что этоcorrect является то, что гораздо лучше сразу потерпеть неудачу с ошибкой, чем использоватьnull который может потерпеть неудачу позже и скрыть причину.

Я не имел дело сisWrapperFor/unwrap на практике, но предположим, чтоunwrap равно нулю в случаеisWrapperFor равно ложь и реализацииisWrapperFor как= null кажется наиболее адекватным в том случае, если объект никогда не может быть оберткой. Разве я не прав? Ivan
Def ??? = throw new UnsupportedOperationException // очень легко добавить в Scala & lt; 2,10
1

As said in comments, this solution doesn't work

Если я хорошо понял вашу проблему, вы также можете назначить значения по умолчанию, как подробно описано вчто значит назначить & quot; _ & quot; в поле в скале?, Вы можете найти больше информации в4.2 Variable Declarations and Definitions изThe Scala Language Specification

Так что вы можете просто сделать:

def unwrap[T](iface: Class[T]): T = _

который установитunwrap сnull без несоответствия типов.

Это правда, я не знал, что это не работает с функциями, что, кстати, грустно. Спасибо за исправление
В 2.9.1 это даетerror: unbound placeholder parameter
16

Это потому что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
Это помогло мне (попытка написать помощника, который бы облегчил вызов библиотеки Java). Как примечание вы знаете, почему вы не можете использовать верхнюю границу AnyRef? Я думал, что Null подтип всех ссылочных классов?
Int имеет тип AnyVal, а типы значений не могут быть обнуляемыми.
хотя @oxbow_lakes упоминает, что бросание предпочтительнее, чем возвращение нулевого значения в большинстве случаев
Не новость, что в Scala есть ненулевые типы ... Я подумалInt обнуляется в отличие от примитива Javaint... Ivan
Ты можешь использоватьAnyRef, но тогда вы должны броситьnull вT, Также я думаю, что более просто сказать, что этот тип должен быть обнуляемым вместо того, чтобы говорить, что это должен быть ссылочный тип.

Похожие вопросы