如何在Scala中创建继承自Set的自定义集合?
解决Scala自定义可变Set的类型兼容与方法实现问题
你的核心问题是没有为自定义Set提供底层数据存储,并且部分方法实现错误(比如clear)。下面是修正后的完整代码,完全兼容Scala标准可变Set的行为,同时保留扩展能力:
import scala.collection._ class TestSet[A] extends mutable.Set[A] with mutable.SetOps[A, mutable.Set, TestSet[A]] { // 用Scala自带的可变HashSet作为底层存储,避免重复造轮子 private val underlying: mutable.HashSet[A] = mutable.HashSet.empty[A] // 返回空的TestSet实例 override def empty: TestSet[A] = new TestSet[A] // 清空底层存储,符合Clearable的Unit返回值要求 override def clear(): Unit = underlying.clear() // 从IterableOnce创建TestSet,委托给伴生对象的from方法 override protected def fromSpecific(coll: IterableOnce[A]): TestSet[A] = TestSet.from(coll) // 返回TestSet的Builder,委托给伴生对象 override protected def newSpecificBuilder: mutable.Builder[A, TestSet[A]] = TestSet.newBuilder // 自定义集合的类名,用于toString等输出 override def className: String = "TestSet" // 添加元素:委托给底层HashSet,返回自身(符合mutable集合的链式调用要求) override def addOne(elem: A): TestSet.this.type = { underlying.addOne(elem) this } // 删除元素:同样委托给底层HashSet,返回自身 override def subtractOne(elem: A): TestSet.this.type = { underlying.subtractOne(elem) this } // 检查元素是否存在:直接用底层HashSet的contains override def contains(elem: A): Boolean = underlying.contains(elem) // 返回迭代器:委托给底层HashSet的迭代器 override def iterator: Iterator[A] = underlying.iterator } object TestSet { // 创建空的TestSet def empty[A]: TestSet[A] = new TestSet[A] // 从IterableOnce创建TestSet,处理TestSet实例的直接返回,其他情况用Builder构建 def from[A](source: IterableOnce[A]): TestSet[A] = source match { case ts: TestSet[A] => ts case _ => (newBuilder[A] ++= source).result() } // 可变参数创建TestSet def apply[A](elem: A*): TestSet[A] = from(elem) // 返回TestSet的Builder,用GrowableBuilder包装empty实例 def newBuilder[A]: mutable.Builder[A, TestSet[A]] = new mutable.GrowableBuilder[A, TestSet[A]](empty[A]) // 隐式转换为Factory,方便集合操作的隐式调用 import scala.language.implicitConversions implicit def toFactory[A](self: this.type): Factory[A, TestSet[A]] = new Factory[A, TestSet[A]] { def fromSpecific(it: IterableOnce[A]): TestSet[A] = self.from(it) def newBuilder: mutable.Builder[A, TestSet[A]] = self.newBuilder } }
关键修改说明:
- 底层存储:新增
private val underlying,用标准mutable.HashSet作为内部存储,避免自己实现哈希表等复杂逻辑,同时保证性能和兼容性。 - clear方法修正:原来的实现返回了不可变Set,不符合
Clearable接口的Unit返回要求,现在直接清空底层存储。 - 核心方法实现:
addOne、subtractOne、contains、iterator全部委托给底层HashSet实现,既符合标准Set的行为,又减少重复代码。 - 类型一致性:所有方法的返回类型严格遵循
SetOps的要求,比如addOne返回TestSet.this.type,保证链式调用的类型正确。
扩展建议
如果后续要添加自定义功能,比如元素添加时的日志、自定义过滤规则等,只需要在对应的方法中添加逻辑即可,比如修改addOne:
override def addOne(elem: A): TestSet.this.type = { println(s"Adding element: $elem") underlying.addOne(elem) this }
内容的提问来源于stack exchange,提问作者Usr654789
相关产品推荐
相关产品推荐

