2012-04-08 38 views
10

Piszę własną prostą implementację javax.sql.DataSource, jedyną metodą, którą muszę wykonać, jest getConnection: Connection, ale interfejs dziedziczy wiele innych metod (których nie potrzebuję) od javax.sql.CommonDataSource i java.sql.Wrapper. Tak więc chciałbym "wdrożyć" te niepotrzebne metody w taki sposób, w jaki one by nie działały, ale zachowałyby się w odpowiedni sposób po wywołaniu. Na przykład zaimplementować boolean isWrapperFor(Class<?> iface) jakJak zwrócić wartość null z ogólnej funkcji w Scali?

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

i chciałbym wdrożyć <T> T unwrap(Class<T> iface) jako

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

Ale ostatnio nie działa: sprawozdania kompilatora niezgodność typów.

Czy będzie prawidłowe stosowanie null.asInstanceOf[T], czy jest lepszy sposób? Oczywiście uważam, że zamiast tego rzucam UnsupportedOperationException w tym konkretnym przypadku, ale IMHO pytanie wciąż może być interesujące.

Odpowiedz

16

Dzieje się tak, ponieważ T może być typem nie podlegającym zerowaniu. To działa, kiedy wymusić T być rodzajem pustych:

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

Nie było nowości, że w Scali są nie-nullowalne typy ... Myślałem, że 'Int' jest zerowalne w przeciwieństwie do prymitywnej Java' int' ... – Ivan

+2

Int jest typu AnyVal, a typy wartości nie są null. – drexin

+1

jak wspomina @oxbow_lakes, rzucanie jest lepsze niż zwracanie wartości zerowej w większości przypadków –

1

Jak powiedział w komentarzach, to rozwiązanie nie działa

Jeśli zrozumiałem swój problem dobrze, można również przypisać wartości domyślne, jak wyjaśniono szczegółowo w what does it mean assign "_" to a field in scala?. Można znaleźć więcej infos w 4,2 deklaracji zmiennych i definicje z The Scala Language Specification

więc można po prostu zrobić:

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

który ustawi unwrap z null bez niedopasowania typu.

+0

W 2.9.1 daje to "błąd: niezwiązany symbol zastępczy" –

+0

To prawda, nie wiedziałem, że to nie działa z funkcjami, co zresztą jest smutne. Dzięki za poprawkę –

6

"Prawidłowym" rozwiązaniem jest zrobienie czegoś, co spowoduje niepowodzenie . Tak:

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

w Scala 2,10, to zostałby wdrożony jako:

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

Ponieważ nie jest to nowa metoda w Predef nazywa ???. Działa to, ponieważ wyrażenie w postaci throw new Exception ma typ Nothing, który jest podtypem dowolnego typu (nazywane jest w kręgach teoretycznych typu).

Dlatego, że jest to poprawne jest to, że jest znacznie lepiej, aby nie od razu z błędem, zamiast używać null które mogą nie później i zaciemniać sprawę.

+0

Nie zajmuję się w praktyce 'isWrapperFor' /' unwrap' w praktyce, ale przypuśćmy, że 'unwrap' ma wartość równą null w przypadku, gdy' isWrapperFor' jest równe false i implementuje 'isWrapperFor' jako' = null' wydaje się być najbardziej odpowiednie na wypadek, gdyby obiekt nigdy nie był opakowaniem. Czy nie mam racji? – Ivan

+0

def ??? = wyrzuć nowy UnsupportedOperationException // bardzo łatwy do dodania w Scali <2.10 –

Powiązane problemy