Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/magento/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala Duck打字新手_Scala - Fatal编程技术网

Scala Duck打字新手

Scala Duck打字新手,scala,Scala,我又开始研究Scala了,我希望这是一个关于duck类型的基本问题,或者可能是关于函数定义的问题。让我解释一下: 给定以下代码: 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 ha

我又开始研究Scala了,我希望这是一个关于duck类型的基本问题,或者可能是关于函数定义的问题。让我解释一下:

给定以下代码:


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
}
所以基本上我有一个“duckTyped”方法,它可以接受任何对象,只要该对象有一个名为“foo”的方法,它是一个Int=>Int函数


为什么类“DoublerThatWontWork”中foo的函数声明不满足函数duckTyped的参数类型?

您的签名说有一个方法foo没有参数,它将函数从Int返回到Int。您拥有的是一个具有Int参数和Int结果的方法

你想要

duck: {def foo(i: Int) : Int}
(参数名称不必匹配)

所以基本上我有一个“duckTyped”方法,可以接受任何对象 只要该对象有一个名为“foo”的方法,该方法是Int=>Int 功能

事实上,这是不正确的。要使其正确,请将其更改为:

一个名为“foo”的无参数方法,返回一个Int=>Int函数

没有方法“是”一个
Int=>Int
,因为那是一种类型,方法没有类型(即,它们不是对象),只有类型签名

类型指示您是什么类型的对象

类型签名指示如何调用方法及其返回的内容

让我们清楚一点,以下两件事是不一样的:

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

第一个方法返回一个
Int
,第二个方法返回一个
Int=>Int
。第一个方法有一个参数列表,有一个
Int
参数,而第二个方法没有参数列表。

注意:这是结构类型,不是duck类型。区别是微妙的,但基本上结构类型是预先检查的,而鸭子类型的语言只是继续尝试一下。@delnan,“鸭子类型”一词只意味着“像鸭子一样走路,像鸭子一样呱呱叫,因此是鸭子”标准。它没有指定是静态的还是动态的。结构类型符合标准,因此可以称为静态duck类型。动态类型化语言所拥有的可以称为动态duck类型化(尽管“duck”在这里是多余的)。@missingfaktor我已经习惯了一个不同的定义,如上所述。稍微正式一点,我想说的区别是:结构类型检查类型-静态或动态-基于结构(例如,在Python中:
hasattr(obj,attr)?
),而duck类型并不真正检查任何东西(例如,只要试着使用成员,如果出现问题,让编译器/运行时抱怨)。注意:我没有说任何关于静态或动态的内容(C++模板是duck类型的,但是类型是静态的,并且在编译时检查模板实例——就在实例之后)。