如何在泛型类中引用伴随对象的方法?

时间:2017-10-26 00:12:15

标签: scala generics

所以我对scala有点新意。

如何编写scala代码以通用方式引用case类的伴随对象中的方法?我尝试了几种不同的方法,似乎找不到一种方法。

下面是一些有效的示例代码,但我必须手动构建每个子类。

例如:

class One extends Act[LetterA] {
    val intro = LetterA.sayhi
}

我宁愿做类似的事情:

class AllOfThem[T <: LettersClass, S <: LettersSingleton] extends Act[T] {
   val intro = S.sayhi
}

但我似乎无法找到有效或将编译的语法。这样做的正确方法是什么,或者我在寻找语言不支持的东西?我知道我可能对我如何构建我的类和特征有点偏僻,但我不确定如何最好地解决这个期望的行为。

另外,有没有办法在Act类的方法'actionTwo'中注释出类似的内容?

示例代码清单:

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
}

1 个答案:

答案 0 :(得分:0)

所以你不能完全你想要的东西,但是你可以非常接近常用的类型类模式:

//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"

所以基本上发生的事情是,无论何时创建新的Act[T],编译器都会尝试通过查找范围内正确类型的任何隐式对象或val来为您填充隐式参数。所以

val a = new Act[LetterA]

实际上会变成

val a = new Act[LetterA](LetterASingleton)

你会注意到单身人士不再是案件类的伴侣对象,这很好。你必须定义一个特征,所以无论它是伴侣对象还是实现它的其他对象,它都没有太大的不同。