[英]How can I reference a companion object's method in a generic class?
So I am a bit new to scala.所以我对 Scala 有点陌生。
How does one write scala code to reference a method from case class's companion object in a generic fashion?如何编写 Scala 代码以通用方式从案例类的伴随对象中引用方法? I have tried a couple of different approaches and can't seem to find one that works.我尝试了几种不同的方法,但似乎找不到一种有效的方法。
Below is some sample code that works, but I have to manually build each subclass.下面是一些有效的示例代码,但我必须手动构建每个子类。
For example:例如:
class One extends Act[LetterA] {
val intro = LetterA.sayhi
}
I would much rather do something like:我更愿意做这样的事情:
class AllOfThem[T <: LettersClass, S <: LettersSingleton] extends Act[T] {
val intro = S.sayhi
}
but I can't seem to find syntax that works or will compile.但我似乎无法找到有效或将编译的语法。 What is the proper way to do this, or am I looking for something that is not supported in the language?这样做的正确方法是什么,还是我正在寻找该语言不支持的东西? I recognise I am probably a little off on how I am structuring my classes and traits, but I am not sure how to best tackle this desired behaviour.我意识到我可能对我如何构建我的类和特征有点偏离,但我不确定如何最好地解决这种期望的行为。
Additionally, is there a way to something similar to what I have commented out in the method 'actionTwo' in the Act class?另外,有没有办法类似于我在 Act 类的方法“actionTwo”中注释的内容?
Sample Code listing:示例代码清单:
trait LettersSingleton {
def sayhi() : String
}
trait LettersClass {
val id : Int
}
// trait Letters extends LettersClass with LettersSingleton { }
object LetterA extends LettersSingleton {
def sayhi = "Hi I am A"
}
object LetterB extends LettersSingleton {
def sayhi = "Hi I am B"
}
case class LetterA( val id : Int ) extends LettersClass { }
case class LetterB( val id : Int, val name:String ) extends LettersClass { }
abstract class Act[ T <: LettersClass ] {
val intro : String
def actionOne( a : T ) = {
println( a.id + " is my id" )
}
def actionTwo() = {
// println( T.sayhi )
}
}
class One extends Act[LetterA] {
val intro = LetterA.sayhi
}
class Two extends Act[LetterB] {
val intro = LetterB.sayhi
}
So you can't do exactly what you want, but you can get very close with the commonly used typeclass pattern:所以你不能完全按照你的意愿去做,但是你可以非常接近常用的类型类模式:
//add a type parameter, now you have a typeclass
trait LettersSingleton[T] {
def sayhi() : String
}
//LettersClass stays the same
object Implicits {
//implicit classes/objects have to go inside an object
//create typeclass instances as implicit objects
implicit object LetterASingleton extends LettersSingleton[LetterA] {
def sayhi = "Hi I am A"
}
implicit object LetterBSingleton extends LettersSingleton[LetterB] {
def sayhi = "Hi I am B"
}
}
import Implicits._
//add an implicit parameter to the class
abstract class Act[ T <: LettersClass ](implicit singleton: LettersSingleton[T]) {
def actionTwo() = {
println( singleton.sayhi )
}
}
(new Act[LetterA]).actionTwo() //prints "Hi I am A"
(new Act[LetterB]).actionTwo() //prints "Hi I am B"
So basically what happens is any time you create a new Act[T]
, the compiler is going to try to fill in the implicit parameter for you by looking for any implicit objects or vals of the correct type in scope.所以基本上发生的事情是任何时候你创建一个新的Act[T]
,编译器都会尝试通过在范围内查找任何隐式对象或正确类型的值来为你填充隐式参数。 So所以
val a = new Act[LetterA]
will actually become实际上会变成
val a = new Act[LetterA](LetterASingleton)
You'll notice that the singletons are no longer the companion objects of the case classes, which is fine.您会注意到单例不再是 case 类的伴生对象,这很好。 You have to define a trait regardless, so it doesn't make much different whether it's the companion object or some other object that implements it.无论如何,您都必须定义特征,因此无论是伴随对象还是实现它的其他对象,都没有太大区别。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.