基于非字符串参数调用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,类型不匹配会直接触发编译错误。Figuretrait本身并未定义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
相关产品推荐
相关产品推荐

