当前位置: 首页 > 知识库问答 >
问题:

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

林弘文
2023-03-14

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

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编译任务捆绑在一起,但我希望有一个解决方案可以作为项目本身的一部分来实现(因为这将使它独立于使用的构建管道,而且它应该比编写一个爬行整个源代码的脚本更简单、更容易维护/扩展)

共有3个答案

习宸
2023-03-14

基于此,我编写了以下内容,满足了我的需求,并覆盖了默认实现:

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'
  }
}

冯星阑
2023-03-14

在我看来,你应该把它抽象化。

// Start writing your ScalaFiddle code here
trait Debugable {
  def debugHashCode:Int
  def debugEquals(obj: Any): Boolean
  def debugToString: String

  override def hashCode(): Int = debugHashCode
  override def equals(obj: Any): Boolean = debugEquals(obj)
  override def toString: String = debugToString
}
//this will not compile
class TestClass extends Debugable { }
//this is OK but you need to implement 3 methods later :)
abstract class TestClass2 extends Debugable {}

https://scalafiddle.io/sf/bym3KFM/0

宏应该是你最后尝试的东西。

时衡虑
2023-03-14

这是接近它(当然是一个改进,比我有),但它并没有完全做到我想要的。如果我有一个类的“链”,那么链的顶端实现这些方法就足够了。

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

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

 类似资料:
  • 必须创建直方图,忽略高于常量的值 我试试这个: 但它不起作用,因为比较返回布尔值。怎么修理?

  • 问题内容: 我希望能够通过在已实例化的对象上调用方法来创建对象的新实例。例如,我有一个对象: 我希望能够调用并拥有两个有机体类型的对象。此时我的方法如下所示: 并且我非常确定它不起作用(我甚至不确定如何测试它。我在本文中尝试了gc方法)。那么,如何使我的对象创建自己的副本,就像我创建的第一个对象(带有)一样,该副本是可访问的? 问题答案: 另一个选项-如果方法中未使用实例(): 这样可以确保生物产

  • 我是IntelliJ的新手,我曾经使用过NetBeans。我的情况如下: > 我创建了类和相应的测试。 我在类中创建了一些方法。 IntelliJ 中是否有任何用于重构测试的功能,以便创建的新方法/函数将在测试类中生成相应的测试函数?我强调测试文件已经生成。 编辑1:我的目标是更新当前的测试,而不是生成一个新的。我期待一个功能,实现新的测试功能到当前的测试。下面是代码片段的情况: 我生成测试。 所

  • 本文向大家介绍layer 刷新某个页面的实现方法,包括了layer 刷新某个页面的实现方法的使用技巧和注意事项,需要的朋友参考一下 一:使用layer.open打开的子页面 1:刷新父页面 2:关闭此页面 2.1 获取窗口索引 (parent.window.name 或者window.name) 2.2 父级执行关闭 二:使用top.layer.open打开子页面 1:先获取页面中iframe 2

  • 问题内容: 我有点困惑。问题是标题,这就是为什么我要问。我在单个VM上运行了JSF + JPA Web应用程序。JPA类具有字段。现在想象一下某个网络用户打开了一个页面并执行以下代码 当另一个Web用户/线程尝试读取该瞬态值时,我期望什么输出: 换句话说,就JVM而言,方法是否总是返回新的类实例或相同或“取决于”的实例?我一直在通过JSR-220寻找答案,但没有成功,任何帮助或文档参考都将不胜感激