3

私は再びScalaをいじくり回していて、ダックタイピングに関する基本的な質問になることを望んでいます。あるいは、それは本当に関数定義に関するものかもしれません。説明させてください:

次のコードが与えられます:


package johnmcase.scala.oneoffs

object DuckTyping extends App {

  def printIt(x:Int, y:Int) = println("Value with " + x + " = " + y);

  // This method will accept ANY object that has a method named foo of type (Int) => Int
  def duckTyped(duck: {def foo: (Int) => Int}) = {
    List(1,2,3,4,5) foreach (i => printIt(i, duck.foo(i)))
  }

  println(new DoublerThatWontWork().foo(5))
  println(new Doubler().foo(5))
  println("DOUBLER:");
  duckTyped(new Doubler());
  println("Squarer:");
  duckTyped(new Squarer());
  println("AlwaysSeven:");
  duckTyped(new AlwaysSeven());
  println("DoublerThatWontWork :");
  duckTyped(new DoublerThatWontWork ()); // COMPILER ERROR!!
}

class DoublerThatWontWork { // WHY??
  def foo(x:Int) = x*2
}

class Doubler {
  def foo = (x:Int) => x*2
}

class Squarer {
  def foo = (x:Int) => x*x
}

class AlwaysSeven {
  def foo = (x:Int) => 7
}

したがって、基本的には、オブジェクトにInt=>Int関数である「foo」という名前のメソッドがある限り任意のオブジェクトを受け入れるメソッド「duckTyped」があります。

クラス「DoublerThatWontWork」のfooの関数宣言が、関数duckTypedのパラメーター型を満たさないのはなぜですか。

4

2 に答える 2

7

あなたの署名は、パラメータのないメソッドfooがあり、IntからIntに関数を返すことを示しています。あなたが持っているのは、IntパラメータとInt結果を持つメソッドです。

あなたが欲しい

duck: {def foo(i: Int) : Int}

(パラメーター名は一致する必要はありません)

于 2012-04-27T17:49:26.177 に答える
4

したがって、基本的には、オブジェクトにInt=>Int関数である「foo」という名前のメソッドがある限り任意のオブジェクトを受け入れるメソッド「duckTyped」があります。

実際、それは正しくありません。正しくするには、次のように変更します。

Int=>Int関数を返す「foo」という名前のパラメーターのないメソッド。

Int => Intメソッドはタイプであり、メソッドにはタイプがなく(つまり、オブジェクトではない)、型シグニチャーだけであるため、メソッドは「ありません」 。

タイプは、あなたがどのようなオブジェクトであるかを示します。

型アノテーションは、メソッドの呼び出し方法とメソッドが返すものを示します。

そして、それを明確にするために、以下の2つのことは同じではありません。

def f(x: Int): Int = x * 2
def f: Int => Int = x => x * 2

最初のメソッドはを返しInt、2番目のメソッドはを返しますInt => Int。最初のメソッドには1つのパラメーターリストがあり、1つIntのパラメーターがありますが、2番目のメソッドにはパラメーターリストがありません。

于 2012-04-27T20:32:01.107 に答える