我偶然发现了这个线程,@prolativ提供了一些花哨的scala 3语法来为对象创建扩展方法
extension (int: Int.type)
def unapply(s: String): Option[Int] = s.toIntOption
但是这让我想到如果有一种方法可以在scala 2中做类似的事情?
我试过了
implicit class IntOps(s: Int.type) {
def unapply(s: String): Option[Int] = s.toIntOption
}
这似乎只是scala 2的翻译,但它不会编译错误object Int is not a case class, nor does it have a valid unapply/unapplySeq member
.
乌利希期刊指南在模式匹配的情况下,有一种方法可以做到这一点-只需添加新对象并匹配它:
object IntOps {
def unapply(s: String): Option[Int] = s.toIntOption
}
,但问题仍然存在-如何添加扩展方法的对象?
隐式类是向对象添加扩展方法的正确方法
implicit class IntOps(obj: Int.type) {
def parse(s: String): Option[Int] = s.toIntOption
}
Int.parse("123") // Some(123)
和unapply
可以用同样的方法加入
implicit class IntOps(obj: Int.type) {
def unapply(s: String): Option[Int] = s.toIntOption
}
Int.unapply("123") // Some(123)
这对模式匹配没有影响
"123" match {
case Int(i) => ??? // doesn't compile: object Int is not a case class, nor does it have a valid unapply/unapplySeq member
}
Scala 2编译器抛出object Int is not a case class, nor does it have a valid unapply/unapplySeq member
的地方在这里:https://github.com/scala/scala/blob/v2.13.10/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala L121-L122
else if (!reallyExists(member))
CaseClassConstructorError(fun, s"${fun.symbol} is not a case class, nor does it have a valid unapply/unapplySeq member")
这是基于符号(scala-reflect
术语中的typeOf[Int.type].decl(TermName("unapply"))
)。这里不检查隐式转换(扩展方法)。
这在Scala 3中被修改:https://github.com/lampepfl/dotty/blob/3.2.2/compiler/src/dotty/tools/dotc/typer/Applications.scala#L1291-L1341编译器尝试对x.unapply
进行类型检查,这包括隐式转换。
unapply
时类(Int
不是case类)编译器也不检查扩展方法
如何查看Scala用于自动生成case类的apply函数的代码?
case class MyClass(i: Int)
MyClass(42) match {
case MyClass(i) => println(i) // 42
}
case class MyClass(i: Int)
object MyClass {
def unapply(mc: MyClass): Option[Int] = Some(100)
}
MyClass(42) match {
case MyClass(i) => println(i) // 100
}
case class MyClass(i: Int)
implicit class MyClassCompanionOps(mc: MyClass.type) {
def unapply(mc: MyClass): Option[Int] = Some(100)
}
MyClass(42) match {
case MyClass(i) => println(i) // 42
}
这个行为在Scala 3中也是一样的。
如何扩展字符串以添加新的unapply函数以用于提取?
用unapply功能充实PartialFunction