如何定义与List几乎相同的类

时间:2014-12-09 22:15:58

标签: scala scala-collections

在Scala中,假设我想要一个类似List [String]的类,除了一些方法,例如toString。

我现在拥有的是

    case class FQN(val names : List[String]) extends LinearSeq[String] {

        def this( params : String* ) { this( List(params : _* )) }

        override def toString() : String = {
              names.reduce((a,b) => b++"."++a)
        }

        override def apply( i : Int ) = names.apply( i ) 

        override def length() = names.length

        override def tail = new FQN( names.tail )  

        override def head = names.head 

        override def isEmpty = names.isEmpty

        def ::( str : String) = new FQN( str :: names ) 

    }

但是,我希望fqn0 ++ fqn1给我一个FQN,就像list0 ++ list1给出一个List'; it currently gives a LinearSeq [String]`。所以事情并不像我想的那样。

我还为FQN提出了一个案例类,以便使equals和hashCode成为我想要的方式,但我不确定这是否是最好的方法。

创建类似于List的类,但以不同方式实现某些方法的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

我的胆量告诉我,你可能最好不要实现一个专门的FQN集合,但隐藏集合作为FQN内部实现的一部分,有效地从接口中删除相应的操作。 FQN。我的意思是,你应该问问自己这个世界是否真的必须FQN作为Seq并且能够使用所有相应的操作,或者它是否足以仅仅添加操作{{1}调度到underyling列表的++操作到++的接口。

然而,Scala家伙显然在推广他们的收藏品方面做得很好,乍看之下,实施自己的收藏并不是一件巨大的痛苦。 documentation I posted in a comment解释了在实现自己的集合时如何重用代码,我建议您阅读它。

简而言之,您希望使用FQN形式的名称混合特征;在您的特定情况xxxLike中,并覆盖方法LinearSeqLike[String, FQN],以使newBuilder: mutable.Builder[String, FQN]之类的方法返回drop

然而,单独的构建器本身并不够强大:FQN(以及我的意外map)等方法可能会将集合中包含的元素映射到不同的类型必须由您的收藏支持。在您的示例中,FQN(“foo”)。map(_。length)不是合法的++,因此结果不能是FQN,但FQN是合法的(至少关于类型)。通过向范围引入隐式FQN("Foo").map(_.toLowercase)值可以解决此问题。

最终的实施可能如下所示:

CanBuildFrom

答案 1 :(得分:0)

基于@Ryan和@KuluLimpa的评论(或者无论如何我对它们的理解),这是一种方法

type FQN = List[String] 

implicit class FQNWithFQNToString( names : List[String] ) {
    def fqnToString() : String = {
        names.reduce((a,b) => b++"."++a)
    }
}

现在您可以使用List[String]完成所有操作,您可以使用FQN。例如,fqn1++fqn2提供FQN。为了得到我想要的字符串,我可以使用fqn.fqnToString

我发现这个答案不太令人满意,原因有两个

  • 弱类型检查。如果Strings的旧列表被视为FQN,则没有错误。特别是我无法定义类型QN(对于限定名称),如果我使用需要QN的{​​{1}},则会出现编译时错误。
  • 现在有两种方法可以将FQN转换为字符串。我必须确保在每种情况下使用正确的一个。如果我为FQN创建了另一个名称QN,那么我将有三种方法将对象转换为字符串。这开始感觉非常非面向对象。