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

基于非字符串参数调用Scala Figure子类构造方法是否可行?

问题描述

我希望基于传入的参数构造对象,但该参数并非字符串。已找到基于字符串实现的方案,但认为存在更优实现方式。现有Scala代码定义如下:

sealed trait Figure
object Figure {
    final case class Circle(radius: Double) extends Figure
    final case class Square(a: Double) extends Figure
}

我尝试定义如下函数,期望通过传入的参数调用对应构造方法:

val construct123: Figure => Either[String, Figure] = (figure: Figure) => Right(figure.apply(1.23))

并希望以construct123(Circle)或construct123(Square)的方式调用,请问这种实现是否可行?

实现可行性分析与修正方案

你的写法不可行,核心问题有两点:

  • Circle和Square是Figure子类的伴生对象,不属于Figure实例范畴,但你定义的construct123参数类型是Figure,类型不匹配会直接触发编译错误。
  • Figure trait本身并未定义apply方法,代码中调用figure.apply(1.23)也无法通过编译。

要实现你想要的功能,推荐两种简洁的修正方案:

方案一:直接接收构造函数作为参数

利用case class伴生对象自动生成的apply方法,定义接受Double => Figure类型的函数:

val construct123: (Double => Figure) => Either[String, Figure] = constructor => Right(constructor(1.23))

调用方式完全符合你的预期:

construct123(Circle)  // 输出:Right(Circle(1.23))
construct123(Square)  // 输出:Right(Square(1.23))

方案二:抽象构造行为(扩展性更强)

如果后续需要支持更多图形类型或复杂构造逻辑,可以先定义一个抽象构造trait:

trait FigureConstructor {
  def create(size: Double): Figure
}

// 让Circle和Square的伴生对象实现该trait
object Circle extends FigureConstructor {
  override def create(size: Double): Figure = Circle(size)
}

object Square extends FigureConstructor {
  override def create(size: Double): Figure = Square(size)
}

// 基于抽象构造trait定义函数
val construct123: FigureConstructor => Either[String, Figure] = constructor => Right(constructor.create(1.23))

调用方式同样简洁:

construct123(Circle)
construct123(Square)

这种方式的优势在于,后续新增图形类型时,只需让其伴生对象实现FigureConstructor即可,无需修改construct123函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 15:20:25