简体   繁体   English

在scala中一般性地实例化特征

[英]Instantiating traits generically in scala

I'm attempting to make a system which allows users to chain together multiple processors. 我正在尝试建立一个允许用户将多个处理器链接在一起的系统。 The difficulty I have is that each processor actually has two bits of information it cares about and I want these handled in a type-safe way. 我遇到的困难是每个处理器实际上都有两个它关心的信息,我希望这些信息以类型安全的方式处理。 I've boiled it down to this problem: 我把它归结为这个问题:

Given: 鉴于:

//First family of stuff
trait A {
  def doA {}
}

trait B {
  def doB {}
} 

//Second family of stuff
trait X {
  def doX {}
}

trait Y {
  def doY {}
} 

I can combine elements from the two families together in 4 flavors: 我可以将两个家庭的元素组合成4种口味:

var f = new A with X {}
f.doA
d.doX

var g = new A with Y {}
//...

Great. 大。 The problem is that I want each of the functions (doA, etc) to return a combination of the two types so that I can chain stuff together. 问题是我希望每个函数(doA等)返回两种类型的组合,以便我可以将东西链接在一起。 Essentially I want to do: trait A { def doThing = { new A with ThingThatImMixedInWithLikeXOrY {} } } 基本上我想做:特质A {def doThing = {新的A与ThingThatImMixedInWithLikeXOrY {}}}

Each processor needs to return an anonymous class which consists of 1) A type known to the processor 2) The type which it was mixed in with. 每个处理器都需要返回一个匿名类,该类包括1)处理器已知的类型2)与之混合的类型。

My first stab was to use generics, something like this: 我的第一个尝试是使用泛型,如下所示:

trait A {
  this : {def makeWithT[TOther]} =>
  def doA = makeWithT[B]
}

trait B {
  this : {def makeWithT[TOther]} =>
  def doB = makeWithT[A]
}

trait X {
  this : {def makeWithS[TOther]} =>
  def doX = makeWithT[Y]
}

trait Y {
  this : {def makeWithS[TOther]} =>
  def doY = makeWithT[Y]
}

class Foo[T, S] extends S with T {
  def makeWithT[OtherT] = new T with OtherT
  def makeWithS[OtherT] = new S with OtherT
}

var f = new Foo[A, X]
f.doA.doB
f.doX.doA
f.doX.doY
...

Obviously, I've run into a catalog of problems: 显然,我遇到了一系列问题:

  1. I can't make a generic class which extends from the type parameters 我不能创建一个从类型参数扩展的泛型类

  2. I can't instantiate my anonymous class via a generic parameter 我无法通过泛型参数实例化我的匿名类

  3. I can't define the return type of the functions in the trait because I don't know the type until it's mixed in with something. 我无法在特征中定义函数的返回类型,因为在它与某些东西混合之前我不知道它的类型。

I'm a bit of a noob when it comes to scala, and I get the feeling that I'm going about this in totally the wrong way and maybe I should be using implicits and the CanBuildFrom pattern. 当谈到scala时,我有点像菜鸟,我觉得我会以完全错误的方式解决这个问题,也许我应该使用implicits和CanBuildFrom模式。 Any help would be greatly appreciated. 任何帮助将不胜感激。

Cheers 干杯

The most known solution for stackable processors is stackable trait 可堆叠处理器最着名的解决方案是可堆叠特性

http://www.artima.com/scalazine/articles/stackable_trait_pattern.html http://www.artima.com/scalazine/articles/stackable_trait_pattern.html

trait StackableRoot {
  def StackablePass (x:Int) : x
}
trait StackableDouble extends StackableRoot {
  def internalPass (x:Int) = 2*x
  abstract override def StackablePass(x:Int) = super.StackablePass(internalPass(x))
}
trait StackableIncrement extends StackableRoot {
  def internalPass (x:Int) = x+1
  abstract override def StackablePass(x:Int) = super.StackablePass(internalPass(x))
}

there is some boilerplate with 有一些样板

  abstract override def StackablePass(x:Int) = super.StackablePass(internalPass(x))

that can't be avoided by packing into parametrized trait since it will require scala to inherit some trait with different parameters multiple times that is prohibited by famous type erasure 通过打包到参数化特征无法避免,因为它需要scala继承一些具有不同参数的特征,这是特征类型擦除所禁止的多次

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM