【问题标题】:ZeroC Ice "checked casts" in ScalaZeroC Ice 在 Scala 中“检查过的演员表”
【发布时间】:2011-02-11 04:13:26
【问题描述】:

ZeroC Ice for Java translates 每个 Slice 接口 Simple (除其他外)一个代理接口 SimplePrx 和一个代理 SimplePrxHelper。如果我有一个ObjectPrx(所有代理的基本接口),我可以通过在SimplePrxHelper 上使用静态方法来检查它是否真的有接口Simple

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。这是正确的吗?

【问题讨论】:

  • 为什么不只是val simple = SimplePrxHelper.checkedCast(obj)?它几乎和你想要的一样短。否则,我不清楚 type 系统应该如何知道这个特定的库已经定义了名为 FooPrxFooPrxHelper 的事物之间的关系,因为该库是以这种方式组织的并且不像Helper<FooPrx> 那样“应该”。
  • 因为我不太担心矮小而不是一般。例如,我不能在方法 foo[AProxyInterface]() : AProxyInterface 中使用这样的强制转换。

标签: scala types ice


【解决方案1】:

应该能够用隐式做一些事情,沿着这些思路:

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())
  }
...

【讨论】:

  • 就此而言,如果您不喜欢周围的所有“隐式对象”,您可以这样做: def castTo[A](obj: ObjectPrx)(implicit mfst: ClassManifest[ A]) = { val helperClass = Class.forName(mfst.erasure.getName + "Helper"); val 方法 = helperClass.getMethod("checkedCast", classOf[ObjectPrx]); Option(method.invoke(null, obj)).asInstanceOf[Option[A]] } ..当然还有异常处理。由于删除了演员表,因此类型不安全,而且速度较慢,但​​只有一个命名的东西。编辑:哎呀,格式化失败!
【解决方案2】:

你可以通过结构类型得到你想要的东西:

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 = FooPrx@da8742

scala> val fp = castTo(FooPrxHelper)(o)
fp: FooPrx = FooPrx@da8742

【讨论】:

  • 我确实想到了这一点,但不幸的是 FooPrxHelper 被定义为一个类(在 Java 中)。我得到“FooPrxHelper 不是一个值”。
  • @Alexey 你可以手工包装所有东西(或者不是真的手工——写一些会为你自动生成代码的东西)。
猜你喜欢
  • 2011-12-03
  • 1970-01-01
  • 2017-11-16
  • 1970-01-01
  • 2020-08-08
  • 1970-01-01
  • 1970-01-01
  • 2010-11-30
  • 2011-02-20
相关资源
最近更新 更多