Scala:创建强制类重新实现某些方法的特性

Scala:创建强制类重新实现某些方法的特性,scala,macros,traits,static-analysis,Scala,Macros,Traits,Static Analysis,我试图实现一个特性,它迫使扩展它的每个类(而不是抽象类)实现某些方法(即使它们已经存在于超类中)。具体来说应该是这样的: trait Debugable { override def hashCode(): Int = ??? override def equals(obj: Any): Boolean = ??? override def toString: String = ??? } 这就是它的特点,也是它的实现: class TestClass { } obje

我试图实现一个特性,它迫使扩展它的每个类(而不是抽象类)实现某些方法(即使它们已经存在于超类中)。具体来说应该是这样的:

trait Debugable {

  override def hashCode(): Int = ???

  override def equals(obj: Any): Boolean = ???

  override def toString: String = ???

}
这就是它的特点,也是它的实现:

class TestClass {

}

object TestClass{
  def main(args: Array[String]): Unit = {
    val t = new TestClass
    println(t)
  }
}
理想情况下,上述代码不应编译(因为可调试类不实现所需的方法)。实际上,这不仅编译,而且不会抛出任何运行时异常(它只接受对象类的默认实现)

到目前为止,没有任何东西能够产生预期的行为。我认为宏可能会有所帮助,但我不确定宏是否可以表达以下内容:

foreach class
     if class.traits.contains(debugable)
         return class.methods.contains(toString)

我知道我可以让一些外部脚本进行检查,并将其与gradle编译任务捆绑在一起,但我希望有一个解决方案可以作为项目本身的一部分实现(因为这将使它独立于所使用的构建管道,而且它应该比编写对整个源代码进行爬网的脚本更简单、更易于维护/扩展)

在我看来,您应该将其抽象化

//在这里开始编写ScalaFiddle代码
特征可调试{
def debugHashCode:Int
def debugEquals(obj:Any):布尔值
def debugToString:字符串
重写def hashCode():Int=debugHashCode
覆盖def equals(obj:Any):布尔值=debugEquals(obj)
重写def toString:String=debugToString
}
//这不会编译
类TestClass扩展了可调试的{}
//这是可以的,但以后需要实现3种方法:)
抽象类TestClass2扩展了可调试的{}

宏应该是您最后尝试的东西

这已经很接近了(当然比我所拥有的有所改进), 但它并不完全符合我的要求。如果我有一条“链条” 类,则链的顶部就足以实现 方法

类型类方法可以帮助实现这一点,例如

trait Debuggable[T] {
  def hashCode(v: T): Int
  def equals(v: T, b: Any): Boolean
  def toString(v: T): String
}

class Foo
class Bar
class Qux extends Foo

object Debuggable {
  implicit val fooDebuggable: Debuggable[Foo] = new Debuggable[Foo] {
    def hashCode(v: Foo) = 42
    def equals(v: Foo, b: Any) = true
    def toString(v: Foo) = "woohoo"
  }
  implicit val barDebuggable: Debuggable[Bar] = new Debuggable[Bar] {
    def hashCode(v: Bar) = 24
    def equals(v: Bar, b: Any) = false
    def toString(v: Bar) = "boohoo"
  }
}

import Debuggable._
def debug[T](v: T)(implicit ev: Debuggable[T]) = ???
debug(new Foo)   // OK
debug(new Bar)   // OK
debug(new Qux)   // Error despite Qux <:< Foo

trait可调试[T]{
def哈希代码(v:T):Int
def等于(v:T,b:Any):布尔值
def toString(v:T):字符串
}
福班
分类栏
类Qux扩展了Foo
对象可调试{
隐式val fooDebuggable:Debuggable[Foo]=新的可调试[Foo]{
def哈希代码(v:Foo)=42
def等于(v:Foo,b:Any)=真
def toString(v:Foo)=“呜呜”
}
隐式val-barDebuggable:Debuggable[Bar]=新的可调试[Bar]{
def哈希代码(v:Bar)=24
def等于(v:Bar,b:Any)=false
def toString(v:Bar)=“boohoo”
}
}
导入可调试的_
def debug[T](v:T)(隐式ev:debugable[T])=???
调试(新Foo)//确定
调试(新条)//确定

debug(new Qux)//错误尽管Qux基于此,我编写了以下代码,它满足了我的需要并覆盖了默认实现:

trait Debuggable_Helper[T]{
  def hashCode(v: T): Int
  def equals(v: T, b: Any): Boolean
  def toString(v: T): String

}

trait Debuggable[T] extends Debuggable_Helper [Debuggable [T]]{
  override def hashCode(): Int = hashCode(this)
  override def equals(b: Any): Boolean = equals(this, b)
  override def toString(): String = toString(this)

}

class Foo extends Debuggable[Foo]{
  def hashCode(v: Debuggable[Foo]) = 42
  def equals(v: Debuggable[Foo], b: Any) = true
  def toString(v: Debuggable[Foo]) = "woohoo"

}
class Qux extends Foo with Debuggable[Qux] //does not compile


object Test{
  def main(args: Array[String]): Unit = {
    println(new Foo)   // OK - prints 'woohoo'
  }
}


这是接近它(当然是一个改进,我有),但它并没有完全做到我想要的。如果我有一个类的“链”,那么链的顶端实现方法就足够了。您不需要扩展任何内容,并且可以为您不需要的类型实现可调试;'我无法访问。我的回答只是问题的简单解决方案。。。这是合适的,太棒了。为了向阅读本文的人澄清这一点:与第一个解决方案不同,trait的方法不会覆盖对象的方法,这可能是一个问题,也可能不是问题,取决于上下文