[英]Why SAM rule doesn't work on parameterless method
// ok
val sam0: MySamWithEmptyParameter = () => 100
// doesn't work
// val sam1: MySamWithParameterless = () => 100
trait MySamWithEmptyParameter {
def receive(): Int
}
trait MySamWithParameterless {
def receive: Int
}
為什么sam1無法覆蓋receive方法? scalac將兩個特征編譯為相同的代碼。
abstract trait TestSAM$MySamWithEmptyParameter extends Object {
def receive(): Int
};
abstract trait TestSAM$MySamWithParameterless extends Object {
def receive(): Int
};
SI-10555談到了這一點。 這是一個簡單的設計決策,只支持顯式的空參數列表,即使兩者都編譯為空參數列表。
規范的相關部分說明 (強調我的):
- 方法m 必須有一個參數列表 ;
這確實有點尷尬,因為eta擴展適用於具有空參數列表的方法。
聯系Lightbend的人。 以下是Scala團隊負責人Adrian Moors的回復:
最初的原因是為了保持規范簡單,但也許我們應該重新審視。 我同意它令人驚訝的是它適用於
def a(): Int
,但不適用於你的例子。在內部,根本沒有定義參數列表的方法和那些(即使為空)的方法被區別對待。 這導致了之前的混亂/錯誤 - 僅舉一例: https : //github.com/scala/scala-dev/issues/284 。
在2.13中,我們正在重新進行eta擴展(它將更積極地應用,但是 - ) - 插入將首先發生)。 我們一直在這方面來回反復,但目前的想法是:
- 0-ary方法是專門處理的:如果期望的類型是sam-等效於Function0,我們eta-expand; 否則,插入
()
(在dotty中,你需要顯式地寫(),除非方法是java定義的) - 我仍然不確定我們是否應該在這里進行eta-expand- 對於所有其他arities,方法引用是eta擴展的,無論期望的類型如何(如果沒有類型不匹配,這可能會在重構參數的方法時隱藏錯誤,但忘記在任何地方應用它們。但是,因為函數是第一個 - 類值,通過簡化參考方法值來構造它們應該很容易)。
結果是我們可以棄用方法值語法(
m _
),因為它只是簡單地寫m
。 (請注意,這與占位符語法不同,如m(, _)
。)(另請參閱此評論的主題: https : //github.com/lampepfl/dotty/issues/2570#issuecomment-306202339 )
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.