在 Scala 中创建泛型类型的实例?
Create an instance of a generic type in Scala?
我正在尝试使用 Scala 进行一些通用编程,并试图弄清楚如何创建类型为 CC
的 class 的实例,如下面的代码所述。我定义了以下抽象特征...
/** 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
}
...然后在伴随对象中隐藏此特征的实现,以强制希望创建自己的特殊 OrderBook
classes 的用户使用特征中定义的接口而不是具体实现中的 subclass 。这是伴随对象...
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
的空实例。我很希望这可以在没有反思的情况下完成。如果需要反射,我愿意接受关于如何避免在这个用例中使用反射的建议。想法?
你可以使用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,例如在 map
和 flatMap
中构建正确的集合。有关详细信息,请阅读 this 答案。
我正在尝试使用 Scala 进行一些通用编程,并试图弄清楚如何创建类型为 CC
的 class 的实例,如下面的代码所述。我定义了以下抽象特征...
/** 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
}
...然后在伴随对象中隐藏此特征的实现,以强制希望创建自己的特殊 OrderBook
classes 的用户使用特征中定义的接口而不是具体实现中的 subclass 。这是伴随对象...
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
的空实例。我很希望这可以在没有反思的情况下完成。如果需要反射,我愿意接受关于如何避免在这个用例中使用反射的建议。想法?
你可以使用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,例如在 map
和 flatMap
中构建正确的集合。有关详细信息,请阅读 this 答案。