如果对象是类

时间:2015-11-22 20:51:36

标签: scala

if(script.isInstanceOf[MouseListener])
    canvas.addMouseListener(script.asInstanceOf[MouseListener])
if(script.isInstanceOf[MouseMotionListener])
    canvas.addMouseMotionListener(script.asInstanceOf[MouseMotionListener])
if(script.isInstanceOf[KeyListener])
    canvas.addKeyListener(script.asInstanceOf[KeyListener])
if(script.isInstanceOf[PaintListener])
    addPaint(script.asInstanceOf[PaintListener])

这感觉非常重复。有没有更好的方法来写它?

2 个答案:

答案 0 :(得分:2)

正如Archeg所提到的,使用模式匹配已经好多了。但对于这种情况,您也可以考虑反思:

def addListeners(target: AnyRef, listener: AnyRef, listenerClasses: Class[_]*) = {
  val targetClass = target.getClass
  listenerClasses.foreach { clazz =>
    if (clazz.isInstance(listener)) {
      try {
        val m = targetClass.getMethod("add" + clazz.getSimpleName, clazz)
        m.invoke(target, listener)
      } catch {
        case e => // log exception
      }
    }
  }
}

addListeners(canvas, script, 
  classOf[MouseListener], classOf[MouseMotionListener], classOf[KeyListener], ...)

或使用Class.getInterfaces.filter(_.getName.endsWith("Listener"))来避免枚举侦听器接口(如果您还想处理从超类继承的接口,则需要一些额外的逻辑)。

答案 1 :(得分:0)

这可能比你开始的更多重复,但它没有任何强制转换,并且它将每个Listener特定代码片段放在适当的Listener特性中:

  trait Listener {
    protected def howToAddToCanvas: Seq[Function1[Canvas, Unit]] = Seq.empty

    def addToCanvas(canvas: Canvas): Unit = howToAddToCanvas.forall(_(canvas))
  }

  trait MouseListener extends Listener {
    override def howToAddToCanvas =
      super.howToAddToCanvas ++ Seq(_.addMouseListener(this))
  }

  trait MouseMotionListener extends Listener {
    override def howToAddToCanvas =
      super.howToAddToCanvas ++ Seq(_.addMouseMotionListener(this))
  }

  . . .

  trait Script extends Listener { . . . }

  object ASpecificScript extends Script with MouseListener with KeyListener with . . .

  . . .

  trait Canvas {
    addMouseListener(listener: MouseListener): Unit
    addMouseMotionListener(listener: MouseMotionListener): Unit
    . . .
  }

这种方法的一个缺点是你必须记住每个Listener特性中 super 的技巧。如果您在一个特征中忘记了该特征,那么该特征将会影响而不是增加.howToAddToCanvas早于extends <trait> with <trait> with <trait> with ...列表中出现的每个特征的NSUserDefaults。除此之外(非常糟糕!),这种方法使编译器确保始终在正确的位置传递适当类型的Listener。

N.B。我没有测试过这个。