简体   繁体   English

定义受特征约束的scala上下文的简写

[英]Shorthand for defining scala context bound in trait

In scala abstract class, if you want to define a context bound, you can simply use, eg [T: ClassTag] in parameter, however this is not possible in trait: 在scala抽象类中,如果要定义上下文绑定,则可以简单地使用,例如在参数中使用[T:ClassTag],但是在trait中是不可能的:

trait Foo[T: ClassTag]

Error:(11, 35) traits cannot have type parameters with context bounds `: ...' nor view bounds `<% ...'
trait Foo[T: ClassTag]
         ^

if you define: 如果您定义:

trait Foo[T] {

  implicit def ctg: ClassTag[T] = implicitly[ClassTag[T]]
}

object Bar extends Foo[Int]

then any attempt to read ctg inside Bar will trigger a StackOverflowError, as the implicit parameter becomes tail-recursive. 那么任何在Bar内部读取ctg的尝试都会触发StackOverflowError,因为隐式参数变为尾递归。

So what's the best way to allow ctg to be defined in a trait that automatically expose subclasses to context bound? 那么,允许在自动将子类暴露于上下文绑定的特征中定义ctg的最佳方法是什么?

There isn't a nice way. 没有一个好方法。 A context bound is short-hand for an implicit parameter, and traits do not have parameters. 上下文绑定是隐式参数的简写,而特征没有参数。 That is, when you write: 也就是说,当您编写:

 class Foo[T : ClasTag]

The compiler de-sugars your code to: 编译器将您的代码分解为以下内容:

 class Foo[T](implicit ev: ClassTag[T])

This is of course not possible with a trait. 当然,这是不可能的。 If you must work around this with a trait, you can make the ClassTag abstract, and force the class that extends it to implement it: 如果必须使用特质解决此问题,则可以将ClassTag抽象化,并强制对其进行扩展的类来实现它:

trait Foo[T] {
  implicit def ctg: ClassTag[T]
}

object Bar extends Foo[Int] {
  implicit val ctg = classTag[Int]
}

This looks slightly better with a class in the middle, so that you don't need to specify Int twice when defining Bar : 好看起来在中间的一类,这样你就不需要指定Int定义时,两次Bar

trait Foo[T] {
  implicit def ctg: ClassTag[T]
}

class FooImpl[T](implicit val ctg: ClassTag[T]) extends Foo[T]

object Bar extends FooImpl[Int]

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

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