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的方法不会覆盖对象的方法,这可能是一个问题,也可能不是问题,取决于上下文