gpt4 book ai didi

Scala 向类添加可堆叠属性

转载 作者:行者123 更新时间:2023-12-04 19:47:38 25 4
gpt4 key购买 nike

我有一个简单的类功能,目前作为案例类实现

case class Feature(value :String)

有多种操作可以用不同的属性装饰特征,例如,有一个函数可以计算特征的出现次数,所以我可能需要一个 CountedFeature。除了计数之外,我可能还需要一个 WeightedFeature、一个 IndexedFeature 等等。

我的直觉说它适合 traits 所以我定义了以下 traits

trait Counted {def count :Long}
trait Weighted {def weight :Double}
trait Indexed {def index :Int}

这会弹出两个问题:1. 我是否需要创建一个具体类来实现每个特征组合(例如,实现 CountedWeightedFeature、CountedIndexedfeature 等),或者是否有某种方法可以避免它。如果我转向更多的装饰品,就不可能为所有组合维护类(class)。2. 我想设计一个函数,根据特征的数量对特征进行加权。它的签名应该类似于:

def computeWeightsByCount(features :List[T <: Feature with Counted]) :List[T with Weighted] = {...}

这里的 T 可能是索引的,也可能不是索引的,所以这个函数应该有某种方法来获取一个类并实例化一个新类,该新类具有堆叠在内部的原始类的所有特征加上一个额外的特征。

在 Scala 中是否有一些优雅的方法可以做到这一点,或者我应该完全重新考虑这种设计?

最佳答案

这个设计在我看来很好,除了不推荐扩展案例类。可以在此处找到原因的简要总结:https://stackoverflow.com/a/12705634/2186890

所以你可能想要重写 Feature就像这样:

trait Feature { def value: String }

现在你可以像这样为模式匹配等定义案例类:

case class CountedFeature(value: String, count: Long) extends Feature with Counted

没有简单的方法可以避免像这样的案例类的组合爆炸,但您可以使用 Feature with Counted 等类型无论你喜欢哪里。请记住,您可以轻松创建匹配类型 Feature with Counted 的对象。在飞行中。例如:

val x: Feature with Counted = new Feature with Counted { val value = ""; val count = 0L }

实现 computeWeightsByCount像你想要的那样有点棘手,因为没有简单的方法来构建 T with Weighted不知道更多类型 T .但它可以用隐式方法来完成。本质上,我们需要有一个定义的路径来生成 T with Weighted来自T对于每个 Feature with Counted您要将此方法应用到的对象。例如,我们从这个开始:

trait Feature { def value: String }
trait Counted { def count: Long }
trait Weighted { def weight: Double }
trait Indexed { def index: Int }

我们要定义computeWeightsByCount就像您在问题中所做的那样,但也采用了一种隐式方法,该方法采用 T和重量,并产生一个 T with Weighted :

def computeWeightsByCount[
T <: Feature with Counted](
features: List[T])(
implicit weighted: (T, Double) => T with Weighted
): List[T with Weighted] = {
def weight(fc: Feature with Counted): Double = 0.0d
features map { f => weighted(f, weight(f)) }
}

现在我们需要定义一个隐式方法来从输入特征中生成加权特征。让我们从获取 Feature with Counted with Weighted 开始来自Feature with Counted .我们将把它放在 Feature 的伴随对象中:

object Feature {
implicit def weight(fc: Feature with Counted, weight: Double): Feature with Counted with Weighted = {
case class FCW(value: String, count: Long, weight: Double) extends Feature with Counted with Weighted
FCW(fc.value, fc.count, weight)
}
}

我们可以这样使用它:

case class FC(value: String, count: Long) extends Feature with Counted
val fcs: List[Feature with Counted] = List(FC("0", 0L), FC("1", 1L))
val fcws: List[Feature with Counted with Weighted] = computeWeightsByCount[Feature with Counted](fcs)

对于您想要为其计算加权计数的任何类型,您需要定义一个类似的此类隐式方法。

不可否认,这远不是一个完美的解决方案。所以是的,你是对的,你可能想重新考虑设计。然而,这种方法的优点是对 Feature 的任何进一步扩展无需对 computeWeightsByCount 进行任何更改即可创建“层次结构” .编写新特征的人也可以提供适当的隐式方法。

关于Scala 向类添加可堆叠属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23442248/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com