簡體   English   中英

為什么SAM規則不適用於無參數方法

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM