ger*_*s.b 6 scala liskov-substitution-principle
Liskov 替换原则指出
如果
S是 的子类型T,则类型的对象T可以替换为类型的对象,S而不会改变该程序的任何所需属性。
但是,在 Scala 中,PartialFunction并非在所有情况下都适用/定义。
trait Function1 {
def apply(x: A): R
}
trait PartialFunction extends Function1 {
def apply(x: A): R
def isDefinedAt(x: A): Boolean
}
Run Code Online (Sandbox Code Playgroud)
如果将 aPartialFunction应用于未定义的值,您将收到异常。
PartialFunction在 Scala 中创建一个的方便方法是使用模式匹配。这样做,您会收到一个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")
Run Code Online (Sandbox Code Playgroud)
fn: String => Int = <function1>
pf: PartialFunction[String,Int] = <function1>
程序:program[](val f: String => Int,val s: String) => (Boolean, Int)
res0:布尔值 = 真
scala.MatchError:两个(java.lang.String 类)
在 scala.PartialFunction$$anon$1.apply(delme.sc:249)
在 scala.PartialFunction$$anon$1.apply(delme.sc:247)
在 ...
这两个fn和pf的亚型Function1,但我不能代替fn的pf,而不会改变我的program。所以在我看来,这违反了 LSP。
你怎么认为 ?
fn并且pf不是 的子类型Function1,因为它们根本不是类型。它们是值,LSP 并没有说您可以使用任何类型的对象T并将其替换为任何类型的对象S:Int当然是 的子类型Int,但替换1为2会使正确的程序不正确。
PartialFunction[String, Int]是 的子类型Function1[String, Int],但是 的契约Function1并没有禁止apply抛出异常,实际上明确允许它:
将此函数的主体应用于参数。它可能会抛出异常。
因此,如果您的程序可以处理 type 的对象Function1[A, B],则它必须已经以apply某种方式处理抛出异常,而PartialFunction抛出 aMatchError只是一种特定情况。
| 归档时间: |
|
| 查看次数: |
129 次 |
| 最近记录: |