2016-09-20 164 views
0

我正在尝试使用Scala的一些泛型编程,并试图找出如何创建如下代码中所述的类型为CC的类的实例。我曾经为了逼谁希望创建自己的特殊OrderBook类使用定义的接口用户自定义以下的抽象特质......在Scala中创建一个泛型类型的实例?

/** Trait defining the interface for an `OrderBook`. 
    * 
    * @tparam O type of `Order` stored in the order book. 
    * @tparam CC type of collection used to store `Order` instances. 
    */ 
trait OrderBook[O <: Order, CC <: collection.GenMap[UUID, O]] { 

    /** All `Orders` contained in an `OrderBook` should be for the same `Tradable`. */ 
    def tradable: Tradable 

    /** Add an `Order` to the `OrderBook`. 
    * 
    * @param order the `Order` that should be added to the `OrderBook`. 
    */ 
    def add(order: O): Unit 

    /** Filter the `OrderBook` and return those `Order` instances satisfying the given predicate. 
    * 
    * @param p predicate defining desirable `Order` characteristics. 
    * @return collection of `Order` instances satisfying the given predicate. 
    */ 
    def filter(p: (O) => Boolean): Option[collection.GenIterable[O]] = { 
    val filteredOrders = existingOrders.filter { case (_, order) => p(order) } 
    if (filteredOrders.nonEmpty) Some(filteredOrders.values) else None 
    } 

    /** Find the first `Order` in the `OrderBook` that satisfies the given predicate. 
    * 
    * @param p predicate defining desirable `Order` characteristics. 
    * @return `None` if no `Order` in the `OrderBook` satisfies the predicate; `Some(order)` otherwise. 
    */ 
    def find(p: (O) => Boolean): Option[O] = existingOrders.find { case (_, order) => p(order) } match { 
    case Some((_, order)) => Some(order) 
    case None => None 
    } 

    /** Return the head `Order` of the `OrderBook`. 
    * 
    * @return `None` if the `OrderBook` is empty; `Some(order)` otherwise. 
    */ 
    def headOption: Option[O] = existingOrders.values.headOption 

    /** Remove and return the head `Order` of the `OrderBook`. 
    * 
    * @return `None` if the `OrderBook` is empty; `Some(order)` otherwise. 
    */ 
    def remove(): Option[O] = { 
    headOption match { 
     case Some(order) => remove(order.uuid) 
     case None => None 
    } 
    } 

    /** Remove and return an existing `Order` from the `OrderBook`. 
    * 
    * @param uuid the `UUID` for the order that should be removed from the `OrderBook`. 
    * @return `None` if the `uuid` is not found in the `OrderBook`; `Some(order)` otherwise. 
    */ 
    def remove(uuid: UUID): Option[O] 

    /* Underlying collection of `Order` instances. */ 
    protected def existingOrders: CC 

} 

...然后这种特质在同伴对象的隐藏实现在特质而不是具体实现的子类中。这里是同伴对象...

object OrderBook { 

    import scala.collection.mutable 
    import scala.collection.parallel 

    def apply[O <: Order, CC <: mutable.Map[UUID, O]](tradable: Tradable): OrderBook[O, CC] = { 
    new MutableOrderBook[O, CC](tradable) 
    } 

    def apply[O <: Order, CC <: parallel.mutable.ParMap[UUID, O]](tradable: Tradable): OrderBook[O, CC] = { 
    new ParallelMutableOrderBook[O, CC](tradable) 
    } 

    private class MutableOrderBook[O <: Order, CC <: mutable.Map[UUID, O]](val tradable: Tradable) 
    extends OrderBook[O, CC] { 

    /** Add an `Order` to the `OrderBook`. 
     * 
     * @param order the `Order` that should be added to the `OrderBook`. 
     */ 
    def add(order: O): Unit = { 
     require(order.tradable == tradable) // can be disabled by compiler? 
     existingOrders(order.uuid) = order 
    } 

    /** Remove and return an existing `Order` from the `OrderBook`. 
     * 
     * @param uuid the `UUID` for the order that should be removed from the `OrderBook`. 
     * @return `None` if the `uuid` is not found in the `OrderBook`; `Some(order)` otherwise. 
     */ 
    def remove(uuid: UUID): Option[O] = existingOrders.remove(uuid) 

    /* Underlying collection of `Order` instances. */ 
    protected val existingOrders: CC = ??? // I want this to be an empty instance of type CC! 

    } 

    private class ParallelMutableOrderBook[O <: Order, CC <: parallel.mutable.ParMap[UUID, O]](val tradable: Tradable) 
    extends OrderBook[O, CC] { 
     /// details omitted for brevity! 
    } 

} 

我想弄清楚如何在我的执行MutableOrderBook创建CC类型的空实例。我希望这可以在没有反思的情况下完成。如果需要反思,我会接受有关如何避免在此用例中使用反思的建议。思考?

+0

你为什么在对象中有'CC <:collection.GenMap [UUID,O]]'类型并且对象中有'CC <:mutable.Map [UUID,O]'的任何原因? – Samar

+0

@samer我想重载apply方法,以便伴随对象变成工厂。类型边界是我打算超载的。我已更新对象来演示此... – davidrpugh

回答

1

您可以使用scala.collection.generic.CanBuildFrom[-From, -Elem, +To],这正是为这个问题。

private class MutableOrderBook[O <: Order, CC <: mutable.Map[UUID, O]] 
    (val tradable: Tradable)(implicit cbf: CanBuildFrom[Nothing, Nothing, CC]) { 
    //give me a CanBuildFrom, which can build a CC out of Nothing. 

    ... 

    val existingOrders: CC = cbf().result 
} 

Scala的集合库使用CanBuildFrom很多内部,例如打造mapflatMap权集合。欲了解更多信息,请阅读this的答案。

+0

我正在尝试实施您的解决方案。但似乎无法获得编译的代码。如果我理解正确,在这种情况下'Elem'类型应该是'(UUID,O)'。但是,从“From”类型使用什么?我是否需要创建自己的定制'CanBuildFrom'或者我应该能够使用已经在作用域中隐式定义的一个?我认为应该已经有一个隐含的范围,用于在任何元素集合(UUID,O)之外构建一个'mutable.Map [UUID,O]子类型的子类型。 – davidrpugh

+0

我们不关心'To'和'From',所以我什么也没用。由于相反,CanBuildFrom与CC作为'To'是CanBuildFrom的一个子类型[Nothing,Nothing,CC],并将满足我们的需求。换句话说,我们不关心它可以构建什么样的元素,因为我们实际上不需要向构建器添加任何东西。你会得到什么错误? –

+0

我得到了错误,说编译器不知道如何用'Nothing'中的'Nothing'元素来构建'CC'类型的集合。 – davidrpugh