2012-04-08 42 views
10

我正在编写我自己的简单javax.sql.DataSource实现,我需要工作的唯一方法是getConnection: Connection,但接口继承了javax.sql.CommonDataSourcejava.sql.Wrapper许多其他方法(我不需要)。所以,我想“实施”那些不需要的方法,这样他们就不会真正起作用,但在被调用时会表现出合适的方式。比如我实现boolean isWrapperFor(Class<?> iface)作为如何从Scala中的泛型函数中返回null?

def isWrapperFor(iface: Class[_]): Boolean = false 

,我想实现<T> T unwrap(Class<T> iface)作为

​​

但最后不工作:编译报告类型不匹配。

使用null.asInstanceOf[T]是否正确?还是有更好的方法?当然,我认为只是抛出UnsupportedOperationException而不是在这种特殊情况下,但恕我直言,这个问题仍然可以是有趣的。

回答

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 
+0

没有新的Scala中有非空类型...我认为'Int'可以与Java原语'int'不同... – Ivan 2012-04-08 20:20:10

+2

Int是AnyVal类型,值类型不可为空。 – drexin 2012-04-08 20:45:57

+1

@oxbow_lakes提到,尽管在大多数情况下抛出比返回null更可取 – 2012-04-09 05:49:22

1

正如评论所说,这个解决方案行不通

如果我明白你的问题好了,你也可以指定默认值,如在what does it mean assign "_" to a field in scala?中详细解释的那样。您可以在4.2变量声明找到更多的相关信息和定义的The Scala Language Specification

因此,你可以简单地做:

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

将设置unwrapnull没有类型不匹配。

+0

在2.9.1中,这给出了一个错误:未绑定的占位符参数 – 2012-04-08 21:10:21

+0

这是真的,我不知道这与功能,它的方式是悲伤的工作。感谢您的更正 – 2012-04-08 21:18:18

6

“正确”的解决办法是做一些事情,立即失败。像这样:

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

斯卡拉2.10,这将是实现:

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

因为在Predef一种新的方法叫做???。这是有效的,因为throw new Exception形式的表达式的类型为Nothing,它是任何类型的子类型(在理论型的圆圈中称为底部)。

的原因,这是正确的它好得多有错误立即失败,而不是使用null以后可能会失败,并混淆的原因。

+0

我在实践中没有处理'isWrapperFor' /'unwrap',但假设'isWrapperFor'等于false,并且''null''实现isWrapperFor'似乎是最多的情况下'unwrap'等于null足以防止对象永远不能成为包装。我不是吗? – Ivan 2012-04-08 22:56:49

+0

def ??? =抛出新的UnsupportedOperationException //很容易在Scala <2.10中添加 – 2012-04-09 05:46:30