簡體   English   中英

覆蓋Scala中的curried函數

[英]Overriding curried functions in Scala

我的印象就是這個

// short syntax
def foo(bar: Bar)(baz: Baz): Quux

這是語法糖

// long syntax
def foo(bar: Bar): (Baz) => Quux

但在繼承方面,我似乎無法將兩者混為一談。 整個樹必須用短語法或長語法定義; 從來沒有。

例如:

case class Context
case class Work

trait ContextualWorker {
  def workWithContext(ctxt: Context)(work: Work): Traversable[Work]
}

class ShortConcreteWorker extends ContextualWorker {
  override def workWithContext(ctxt: Context)(work: Work) = Nil
}

class LongConcreteWorker extends ContextualWorker {
  // error on next line: method workWithContext overrides nothing    <-------------
 override def workWithContext(ctxt: Context): (Work) => Traversable[Work] = {
    val setupCode = 1
    { work => Nil }
  }
}

如果我更改特征以使用長語法,則ShortConcreteWorker不會編譯。

這些是不可互換/可繼承的原因嗎? 你是怎么得到它的?

現在,最靈活的方法似乎是在長語法中定義樹,也許如此委托給ShortConcreteWorker中的實現類:

case class Context
case class Work

trait ContextualWorker {
  def workWithContext(ctxt: Context): (Work) => Traversable[Work]
}

class ShortConcreteWorker extends ContextualWorker {
  override def workWithContext(ctxt: Context) = workWithContextImpl(ctxt)_ 
  private def workWithContextImpl(ctxt: Context)(work: Work) = Nil
}

class LongConcreteWorker extends ContextualWorker {
  override def workWithContext(ctxt: Context): (Work) => Traversable[Work] = {
    val setupCode = 1
    { work => Nil }
  }
}

所描述的兩種方法非常簡單地具有不同的簽名。 REPL證實了這一點:

scala> def foo1(a: Int)(b: Int): Int = a + b
foo1: (a: Int)(b: Int)Int

scala> def foo2(a: Int): (Int => Int) = (b: Int) => a + b
foo2: (a: Int)Int => Int

第一個是需要兩個參數的函數,在單獨的參數列表中給出,並返回一個Int 第二個是一個函數,它有一個參數,並返回從函數 IntInt 雖然這兩件事在概念上是相似的,但實際上它們是不同的結構,而Scala就是這樣對待它們的。

這不僅限於具有多個參數列表的函數。 它的工作方式與此相同:

scala> def foo3(a: Int): Int = a + 1
foo3: (a: Int)Int

scala> def foo4: (Int => Int) = (a: Int) => a + 1
foo4: Int => Int

請注意,使用方式也有不同的后果。 使用foo2 ,因為它只接受一個參數,我們可以用一個參數調用它。 但是, foo1需要兩個參數,因此我們不能簡單地用一個參數調用它。 但是,您可以使用_語法將其轉換為可調用函數。

foo2(2)    // Int => Int = <function1>
foo1(2)    // error: missing arguments for method foo1
foo1(2) _  // Int => Int = <function1>

所以直接回答你的問題:他們不可互換的原因是因為他們不一樣。 如果它們是相同的,我們就可以用同樣的方式調用它們。 如果您可以在擴展時更改簽名,Scala將如何知道允許哪種調用語法? “解決”這種方法的方法是簡單地使簽名保持一致。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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