2017-09-09 4 views
4

사용자 정의 Seq 작업 다음 사항을 고려하십시오스칼라에서 바운드 형식 매개 변수를 사용하여 사용자 지정 Seq를 만드는 방법은 무엇입니까?

class MySeq[B](val s: Seq[B]) 
extends Seq[B] 
with GenericTraversableTemplate[B, MySeq] 
with SeqLike[B, MySeq[B]] { 
    override def companion = MySeq 

    def iterator = s.iterator 

    def apply(i: Int) = s(i) 

    def length = s.length 

    override def toString = s map { _.toString } mkString("\n") 
} 
object MySeq extends SeqFactory[MySeq] { 
    implicit def canBuildFrom[B]: CanBuildFrom[Coll, B, MySeq[B]] = 
     new GenericCanBuildFrom[B] 
    def newBuilder[B] = new ListBuffer[B] mapResult (x => new MySeq(x.toSeq)) 
} 

가 나는이 형식 매개 변수 B에 바인딩 부과하고 싶습니다. 즉,이 같은 (작동하지 않는) 좋아하는 것 :

class MyA 

class MySeq[+B <: MyA](val s: Seq[B]) 
extends Seq[B] 
with GenericTraversableTemplate[B, MySeq] 
with SeqLike[B, MySeq[B]] { 
    override def companion = MySeq // Type Mismatch Here 

    def iterator = s.iterator 

    def apply(i: Int) = s(i) 

    def length = s.length 

    override def toString = s map { _.toString } mkString("\n") 
} 
object MySeq extends SeqFactory[MySeq] { 
    implicit def canBuildFrom[B]: CanBuildFrom[Coll, B, MySeq[B]] = 
     new GenericCanBuildFrom[B] 
    // Type Mismatch in the line below 
    def newBuilder[B] = new ListBuffer[B] mapResult (x => new MySeq(x.toSeq)) 
} 

을하지만 난 표시 줄에 다음과 같은 유형의 불일치 오류를 얻을 : 나는이 문제를 해결하기 위해 노력했다

inferred type arguments [B] do not conform to 
class MySeq's type parameter bounds [+B <: MyA] 
Main.scala line 49 

type mismatch; 
found : countvotes.structures.MySeq.type 
required: scala.collection.generic.GenericCompanion[Seq]  
Main.scala line 36 

type mismatch; 
found : MySeq[B(in class MySeq)] 
required: MySeq[B(in method newBuilder)]  
Main.scala line 49 

type mismatch; 
found : scala.collection.immutable.Seq[B(in method newBuilder)] 
required: Seq[B(in class MySeq)]  
Main.scala line 49 

CanBuildFrom 및 newBuilder의 형식 매개 변수에 경계를 추가하지만 다른 오류 메시지가 나타납니다.

유형 매개 변수가 바인딩 된 맞춤 Seq을 어떻게 만듭니 까?

+1

당신이 후 오히려 컬렉션을 확장 상한 요구 사항 래퍼 클래스에서 캡슐화하고 어떤 이유는 여기에

class MySeq[+B <: MyA](val s: Seq[B]) extends Seq[B] with SeqLike[B, MySeq[B]] { override def iterator = s.iterator override def apply(i: Int) = s(i) override def length = s.length override def toString = s.map(_.toString).mkString("\n") override def companion = s.companion protected[this] override def newBuilder: mutable.Builder[B, MySeq[B]] = new mutable.Builder[B, MySeq[B]] { private[this] val base = s.genericBuilder[B] override def +=(elem: B) = { base += elem; this } override def clear() = base.clear() override def result() = new MySeq[B](base.result()) } } object MySeq { implicit def canBuildFrom[A <: MyA]: CanBuildFrom[MySeq[_], A, MySeq[A]] = ??? } val list = List(new MyA, new MyA, new MyA, new MyA) val vect = list.toVector val mLst = new MySeq(list) val mVec = new MySeq(vect) { val res = mLst.filter(_.hashCode != list.head.hashCode) implicitly[res.type <:< MySeq[MyA]] } { val res = (mVec: Seq[MyA]).map(identity) assert(res.isInstanceOf[Vector[_]]) } { val res = (mLst: Seq[MyA]).map(identity) assert(res.isInstanceOf[List[_]]) } 

+0

이유는 더 우아 할 것입니다. 이 클래스에서는'map'과'filter'를 많이 사용하게 될 것이고, 매번 수동으로 unwrap하고 re-wrap하는 것은 불편할 것입니다. – Bruno

답변

2

나는 라인 (26)에 오류를받지 못했습니다 : 다른

어쩌면
override def companion = MySeq 

무언가가 그 원인입니다.

어쨌든 GenericCompanion[MySeq] (수퍼 유형이 SeqFactory) 일 수는 없습니다. 그 이유는 GenericCompanion[Coll]A (newBuilder의 서명 참조)에 대해 Coll[A]을 구성 할 수 있다는 것을 의미합니다. genericBuilder이 불가능하기 때문에 MySeq[A] <: GenericTraversableTemplate[A, MySeq]도 가질 수 없습니다. 이것은 의미가 있습니다. MySeq은 요소가 모두 MyA이되기를 바라기 때문에 실제로 "일반적인 컬렉션"이 아닙니다.

용액은 이어야하며 (extends Seq은 무료입니다). 그런 다음 companion에 대해 두 가지 선택 사항이 있습니다. Seq에서 기본값이 될 수도 있고 s.companion이 될 수도 있습니다. 첫 번째 경우에 ((as: MySeq[A]): Seq[A]).map(...)List을 생성합니다 (런타임에는 컴파일 타임에만 일반 Seq입니다). 두 번째 방법은 as.s이 무엇인지에 달려 있습니다 (다시 말하지만 컴파일 타임에는 Seq 만 표시됨). 그래도 extends SetLike을 유지할 수 있습니다.

다음 사용자 정의 CanBuildFrom : MySeq.canBuildFrom[A <: MyA]: CanBuildFrom[MySeq[A], A, MySeq[A]]을 제공하고 MySeq#newBuilder을 정의해야합니다.

class MyA 

class MySeq[+A <: MyA](val s: Seq[A]) 
    extends Seq[A] 
    with SeqLike[A, MySeq[A]] 
{ 
    override def iterator = s.iterator 
    override def apply(i: Int) = s(i) 
    override def length = s.length 

    override def toString = s.map(_.toString).mkString("\n") 

    override def companion = s.companion 
    protected[this] override def newBuilder = MySeq.newBuilder 
} 

object MySeq { 
    def newBuilder[A <: MyA] = new mutable.Builder[A, MySeq[A]] { 
    private[this] val base = Seq.newBuilder[A] 
    override def +=(elem: A) = { base += elem; this } 
    override def clear() = base.clear() 
    override def result() = new MySeq[A](base.result()) 
    } 

    implicit def canBuildFrom[A <: MyA]: CanBuildFrom[MySeq[_], A, MySeq[A]] = new CanBuildFrom[MySeq[_], A, MySeq[A]] { 
    def apply(from: Election[_]) = newBuilder 
    def apply() = newBuilder 
    } 
} 
0

구현 canBuildFrom 위에서 HTNW의 허용 대답에 따라 전체 MWE입니다 ?