You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Scaladoc子类中覆写@define宏定义?

问题解答:Scaladoc中跨类替换@define变量的实现

首先明确:这不是Scaladoc的bug,而是它的静态文本替换设计导致的——@define变量是在定义文档的类/特质内部完成替换的,基类中foo方法的$Word在生成基类Scaladoc时就已经被替换成base-word了,子类继承的是这个已经替换完成的文档文本,而非带占位符的模板,所以子类的@define Word无法影响基类方法的文档内容。

下面提供两种可行的解决方案:

方法1:使用Scaladoc宏(推荐,实现动态替换)

Scaladoc宏允许你在生成文档时动态读取当前类的注解信息,从而实现跨类的变量替换。你需要编写一个简单的宏来完成这个逻辑:

第一步:实现Scaladoc宏

创建一个宏类(注意需要放在单独的编译模块,或者作为编译时依赖):

import scala.reflect.macros._
import scala.language.experimental.macros

class DocWordMacro(val c: blackbox.Context) {
  def getWord: c.Tree = {
    import c.universe._
    // 从当前类的@define注解中提取Word的值
    val wordValue = c.enclosingClass.annotations
      .find(_.tree.tpe =:= typeOf[scala.annotation.meta.Define])
      .flatMap { ann =>
        ann.tree.children.collectFirst {
          case Literal(Constant(s: String)) if s.startsWith("Word=") => s.substring(5)
        }
      }
      .getOrElse("base-word") // 基类默认值
    
    q""" "Does a " + $wordValue """
  }
}

object DocMacros {
  def wordPlaceholder: String = macro DocWordMacro.getWord
}

第二步:在类中使用宏

修改你的基类和子类,用宏替换原来的$Word占位符:

/**
 * @define Word base-word
 */
class DocTestBase {
  /** ${DocMacros.wordPlaceholder}
   *
   * @return
   */
  def foo = 1
}

/**
 * @define Word subclass word!
 */
class DocTestSubclass extends DocTestBase

当生成Scaladoc时,宏会在子类的上下文执行,自动读取子类的@define Word值,替换到方法文档中,达到你预期的效果。

方法2:子类手动重写方法并替换文档

如果不想引入宏,也可以在子类中重写方法,手动替换文档内容:

/**
 * @define Word base-word
 */
class DocTestBase {
  /** Does a $Word
   *
   * @return
   */
  def foo = 1
}

/**
 * @define Word subclass word!
 */
class DocTestSubclass extends DocTestBase {
  /** Does a $Word
   *
   * @inheritdoc // 继承基类方法的其他文档内容
   */
  override def foo = super.foo
}

这种方法的缺点是需要在每个子类中重复重写方法,适合子类数量较少的场景。


内容的提问来源于stack exchange,提问作者Dylan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:05:00