2016-11-03 48 views
3

的里氏替換原則狀態'PartialFunction extends Function`是否違反LSP?

if S is a subtype of T , then objects of type T may be replaced with objects of type S without altering any of the desirable properties of that program.

然而,在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 (of class java.lang.String)

   at scala.PartialFunction$$anon$1.apply(delme.sc:249)

   at scala.PartialFunction$$anon$1.apply(delme.sc:247)

   at ...

兩個fnpfFunction1亞型,但我不能代替通過pffn不會改變我的program。所以我認爲這是對LSP的違反。

您認爲如何?

+0

這將主要是一個意見件。你有關於應用或使用更一般問題的更具體問題嗎? – wheaties

+0

絕對不是。我只是要求其他開發人員的建議。也許我應該將它發佈到另一個社區? –

+1

你也可以定義一個'Function1',它僅僅爲''one'''以外的所有輸入引發異常。你違反LSP的論點是拋出一個異常可能是一個不希望的改變,但是一個'Function1'仍然可以有輸入來拋出異常。例如'的BigDecimal( 「ABC」)'。 'PartialFunction'和'Function1'之間的主要區別在於你有一個內置的方法來檢查元素是否被首先定義。 –

回答

3

fnpf不是Function1的子類型,因爲它們根本不是類型。它們是值,並且LSP沒有說你可以採取T類型的任何對象並將其替換爲S類型的任何對象:Int肯定是Int的子類型,但用2代替1可以使正確的程序不正確。

PartialFunction[String, Int]Function1[String, Int]一個亞型,但Function1合同不會拋出異常禁止apply,事實上明確允許:

Apply the body of this function to the argument. It may throw an exception.

所以,如果你的程序可以處理Function1[A, B]類型的對象,它必須處理apply以某種方式拋出異常,而PartialFunction拋出MatchError只是一個特例。

0

根據維基百科,還有一個額外的條款需要LSP來應用。

No new exceptions should be thrown by methods of the subtype, except where those exceptions are themselves subtypes of exceptions thrown by the methods of the supertype.

所以(假設維基百科是正確的),沒有PartialFunction不違反LSP,因爲它並不適用於這種情況。

編輯:有一個在scaladoc附加信息:(Scaladoc Function1

Note that Function1 does not define a total function, as might be suggested by the existence of PartialFunction. The only distinction between Function1 and PartialFunction is that the latter can specify inputs which it will not handle.

所以想這將是PF的另一種方式是不是FN的子類型。

FN:字符串=>詮釋

PF:響應字符串=>詮釋

進一步編輯的子集來評論: 不,我爭辯說,LSP完全不適用。對於申請S的LSP,不得拋出新的異常。 S在這裏確實會拋出新的異常,所以LSP不會被違反,因爲它不適用。

+0

但是'PartialFunction'會拋出'Function'沒有的'scala.MatchError'嗎?或者你是否認爲'Function'可以拋出任何東西?當然,這裏的例外並沒有真正表達出來,所以它也可能是。 – Bergi

+0

我已經放了更多的東西。我對類型理論的基礎知識是不存在的,所以我非常願意完全錯誤。 –

+0

啊,我明白你的引用是因爲這種異常行爲被*侵犯的LSP,而不是根本不適用。 – Bergi