里氏替换原则指出:
如果
然而,在 Scala 中,
如果你对一个未定义的值应用
在 Scala 中创建
如果
S
是 T
的一个子类型,那么可以用类型为 S
的对象代替类型为 T
的对象,而不会改变程序的任何良好属性。然而,在 Scala 中,
PartialFunction
并非适用于所有情况/定义。trait Function1 {
def apply(x: A): R
}
trait PartialFunction extends Function1 {
def apply(x: A): R
def isDefinedAt(x: A): Boolean
}
如果你对一个未定义的值应用
PartialFunction
,你将会收到一个异常。在 Scala 中创建
PartialFunction
的一种方便的方法是使用模式匹配。这样做,当出现未定义的值时,你将会收到一个 MatchError
。val fn:Function1[String, Int] = s => s.length
val pf:PartialFunction[String, Int] = {
case "one" => 3
}
def program(f:Function1[String, Int], s:String):(Boolean, Int) = (
f.isInstanceOf[Function1[String, Int]], f(s)
)
program(fn, "one") == program(pf, "one")
program(fn, "two") == program(pf, "two")
fn:String => Int = <function1>
pf:PartialFunction[String,Int] = <function1>
program:program [](val f:String => Int,val s:String)=>(Boolean,Int)
res0:Boolean = true
scala.MatchError:two(class java.lang.String的实例)
at scala.PartialFunction$$anon$1.apply(delme.sc:249)
at scala.PartialFunction$$anon$1.apply(delme.sc:247)
at ...
fn
和pf
都是Function1
的子类型,但我不能将fn
替换为pf
而不改变我的program
。因此,在我看来,这是LSP的一种违反。
你怎么看?
Function1
,对于除了“one”之外的所有输入都会抛出异常。您违反LSP的论点是抛出异常可能是一种不良的改变,但是Function1
仍然可以具有抛出异常的输入。例如BigDecimal(“abc”)
。PartialFunction
和Function1
之间的主要区别在于您内置了一种检查元素是否已定义的方法。 - Michael Zajac