2010-04-22 5 views
2

ZeroC Ice для Java translates каждый интерфейс Slice Simple в (помимо прочего) прокси-интерфейс SimplePrx и прокси SimplePrxHelper. Если у меня есть ObjectPrx (базовый интерфейс для всех прокси-серверов), я могу проверить, действительно ли это интерфейс Simple, используя статический метод на SimplePrxHelper:ZeroC Ice «проверенные листы» в Scala

val obj : Ice.ObjectPrx = ...;  // Get a proxy from somewhere... 

val simple : SimplePrx = SimplePrxHelper.checkedCast(obj); 
if (simple != null) 
    // Object supports the Simple interface... 
else 
    // Object is not of type Simple... 

Я хотел написать метод castTo, так что я мог бы заменить вторая линия с

val simple = castTo[SimplePrx](obj) 

или

val simple = castTo[SimplePrxHelper](obj) 

насколько я могу видеть, тип системы Scala является п достаточно выразительно, чтобы позволить мне определить castTo. Это верно?

+1

Почему не просто 'val simple = SimplePrxHelper.checkedCast (obj)'? Это почти так же мало, как то, что вы хотите. В противном случае мне непонятно, как система _type_ должна знать, что эта конкретная библиотека определила взаимосвязь между вещами, называемыми «FooPrx» и «FooPrxHelper», учитывая, что библиотека организована таким образом, а не как «Помощник » должен быть. –

+0

Потому что я меньше беспокоюсь о том, чтобы быть коротким, чем быть родовым. Я не могу, например, использовать такой листинг внутри метода 'foo [AProxyInterface](): AProxyInterface'. –

ответ

4

Должно быть в состоянии сделать что-то с implicits, вдоль этих линий:

object Casting { 
    trait Caster[A] { 
    def checkedCast(obj: ObjectPrx): Option[A] 
    } 

    def castTo[A](obj: ObjectPrx)(implicit caster: Caster[A]) = 
    caster.checkedCast(obj) 

    implicit object SimplePrxCaster extends Caster[SimplePrx] { 
    def checkedCast(obj: ObjectPrx) = Option(SimplePrxHelper.checkedCast(obj)) 
    } 
} 

Тогда вы просто принести вещи в область видимости где вы хотите их использовать:

package my.package 

import Casting._ 

... 
    def whatever(prx: ObjectPrx) { 
    castTo[SimplePrx](prx) foreach (_.somethingSimple()) 
    } 
... 
+0

В этом случае, если вам не нравятся все «неявные объекты», вы можете сделать это следующим образом: def castTo [A] (obj: ObjectPrx) (неявный mfst: ClassManifest [A]) = { val helperClass = Class.forName (mfst.erasure.getName + "Helper"); val method = helperClass.getMethod ("checkedCast", classOf [ObjectPrx]); Опция (метод.invoke (null, obj)). AsInstanceOf [Опция [A]] } ..plus исключение обращение конечно. Не как безопасный тип благодаря стиранию, а скорее медленнее, но только одна именованная вещь. Редактировать: eek, форматирование не работает! –

1

Вы можете получить что-то вроде того, что вы хотите со структурными типами:

def castTo[A](helper: { def checkedCast(o: Object): A })(o: Object) = { 
    helper.checkedCast(o) 
} 
class FooPrx { } 
object FooPrxHelper { 
    def checkedCast(o: Object): FooPrx = o match { 
    case fp : FooPrx => fp 
    case _ => null 
    } 
} 

scala> val o: Object = new FooPrx 
o: java.lang.Object = [email protected] 

scala> val fp = castTo(FooPrxHelper)(o) 
fp: FooPrx = [email protected] 
+0

Я действительно думал об этом, но, к сожалению, 'FooPrxHelper' определяется как класс (в Java). Я получил «FooPrxHelper - это не значение». –

+0

@Alexey Вы можете обернуть все вручную (или не вручную) - напишите что-нибудь, что сделает автоматическое создание кода для вас). –