如何在一个通用类中引用伴生对象的方法?

3

我还是对Scala有些陌生。

如何编写Scala代码以通用的方式引用案例类(case class)的伴生对象中的方法?我尝试了几种不同的方法,但似乎找不到可行的解决方案。

以下是一些示例代码,它可以工作,但我必须手动构建每个子类。

例如:

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

所以你不能做到完全想要的,但是你可以使用常用的类型类模式来实现非常接近:

//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 a = new Act[LetterA]

实际上将变成

val a = new Act[LetterA](LetterASingleton)

你会注意到单例对象不再是案例类的伴生对象,这没关系。无论如何,你都必须定义一个trait,因此它是伴生对象还是实现它的其他对象并没有太大区别。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接