如何在不使用抽象类的情况下强制进行类型推断

时间:2013-09-30 10:03:17

标签: scala

我有一个工厂对象,它创建了一些元素的实例(这是一个内部类型)。我还有一个适用于工厂创建的元素的操作。这是代码:

class Factory {
  class Element private [Factory] (val int:Int)
  def create(from:Int) = new Element(from)
}

class OperationOnFactoryElement(val factory:Factory) {
  def apply(element:factory.Element) = factory.create(element.int + 1)
}

val factory = new Factory

val op = new OperationOnFactoryElement(factory)

val someElement = factory.create(1)

op(someElement) // this causes an error!!

//<console>:13: error: type mismatch;
// found   : factory.Element
// required: op.factory.Element
//              op(someElement)
//                 ^

很明显,编译器希望我使用OperationOnFactoryElement中嵌入的工厂来接受操作。但是,如果我需要在该元素上定义更多操作,那么它就成了问题,因为我不能,例如组合这两个操作。我提出了这个解决方案:

class Factory {
  class Element private [Factory] (val int:Int)
  def create(from:Int) = new Element(from)
}

abstract class OperationOnFactoryElement {
  val factory:Factory
  def apply(element:factory.Element) = factory.create(element.int + 1)
}

val myfactory = new Factory

val op = new OperationOnFactoryElement {
val factory:myfactory.type = myfactory
}
val someElement = myfactory.create(1)

op(someElement) // this works

然而,我被迫将我的操作变成抽象类。我的问题是:

有没有办法在不使类OperationOnFactoryElement抽象的情况下实现相同的结果?

1 个答案:

答案 0 :(得分:2)

您可以使用Factory#Element告诉apply期望在Element

中定义Factory
 class OperationOnFactoryElement(val factory:Factory) {
   def apply(element:Factory#Element) = factory.create(element.int + 1)
 }

通过此更改,您的第一个代码示例应该按原样运行。

scala> class Factory {
     |   class Element private [Factory] (val int:Int)
     |   def create(from:Int) = new Element(from)
     | }
defined class Factory

scala> class OperationOnFactoryElement(val factory:Factory) {
     |    def apply(element:Factory#Element) = factory.create(element.int + 1)
     |  }
defined class OperationOnFactoryElement

scala> val factory = new Factory
factory: Factory = Factory@650b5efb

scala> val op = new OperationOnFactoryElement(factory)
op: OperationOnFactoryElement = OperationOnFactoryElement@33abb81e

scala> val someElement = factory.create(1)
someElement: factory.Element = Factory$Element@bebf1eb

scala> op(someElement)
res0: op.factory.Element = Factory$Element@6176959c

scala> someElement.int
res1: Int = 1

scala> res0.int
res2: Int = 2