java方法和函数的区别是什么_Scala中方法和函数之间的区别

吉姆在his blog post中已经涵盖了这个,但我在这里发布简报以供参考 .

首先,让我们看看Scala规范告诉我们的内容 . 第3章(类型)告诉我们函数类型(3.2.9)和方法类型(3.3.1) . 第4章(基本声明)涉及 Value 声明和定义(4.1),变量声明和定义(4.2)以及函数声明和定义(4.6) . 第6章(表达式)讲的是匿名函数(6.23)和方法值(6.7) . 奇怪的是,功能值在3.2.9中被说出一次,而在其他地方则没有 .

Function Type (大致)是一种形式(T1,...,Tn)=> U,它是标准库中特征 FunctionN 的简写 . Anonymous Functions 和 Method Values 具有函数类型,函数类型可以用作值,变量和函数声明和定义的一部分 . 实际上,它可以是方法类型的一部分 .

Method Type 是 non-value type . 这意味着有一个 no 值 - 没有对象,没有实例 - 带有方法类型 . 如上所述, Method Value 实际上有 Function Type . 方法类型是一个 def 声明 - 除了它的主体之外的所有关于_785622的声明 .

Value Declarations and Definitions 和 Variable Declarations and Definitions 是 val 和 var 声明,包括类型和值 - 分别可以是 Function Type 和 Anonymous Functions or Method Values . 请注意,在JVM上,这些(方法值)是使用Java调用"methods"实现的 .

Function Declaration 是 def 声明,包括类型和正文 . 类型部分是方法类型,主体是表达式或块 . 这也是在JVM上实现的,Java调用"methods" .

最后, Anonymous Function 是 Function Type 的实例(即特征的实例 FunctionN ), Method Value 是同一个东西!区别在于方法值是从方法创建的,可以通过后缀下划线( m _ 是对应于"function declaration"( def ) m 的方法值),也可以通过称为eta-expansion的过程创建,这类似于方法的自动转换发挥作用 .

这就是规范所说的,所以让我把它放在前面: we do not use that terminology! 它导致所谓的"function declaration"之间的混淆,这是程序的一部分(第4章 - 基本声明)和"anonymous function",这是一个表达式和"function type",这是一种类型 - 特征 .

下面的术语,由经验丰富的Scala程序员使用,从规范的术语进行了一处更改: instead of saying function declaration, we say method . 甚至方法声明 . 此外,我们注意到值声明和变量声明也是实用的方法 .

So, given the above change in terminology, here's a practical explanation of the distinction.

函数是一个包含 FunctionX 特征之一的对象,例如 Function0 , Function1 , Function2 等 . 它也可能包括 PartialFunction ,它实际上扩展了 Function1 .

让我们看看其中一个特征的类型签名:

trait Function2[-T1, -T2, +R] extends AnyRef

这个特性有一个抽象方法(它也有一些具体的方法):

def apply(v1: T1, v2: T2): R

这告诉我们所有人都应该了解它 . 函数有一个 apply 方法,它接收类型为T1,T2,...,TN的N个参数,并返回 R 类型的东西 . 它在接收的参数上是反变量的,并且在结果上是共变量 .

该差异意味着 Function1[Seq[T], String] 是 Function1[List[T], AnyRef] 的子类型 . 作为子类型意味着它可以用来代替它 . 人们可以很容易地看到,如果我打算调用 f(List(1, 2, 3)) 并期望 AnyRef 返回,则上述两种类型中的任何一种都可以工作 .

现在,方法和函数的相似性是什么?好吧,如果 f 是一个函数而 m 是作用域的本地方法,则可以像这样调用它们:

val o1 = f(List(1, 2, 3))

val o2 = m(List(1, 2, 3))

这些调用实际上是不同的,因为第一个只是一个语法糖 . Scala将其扩展为:

val o1 = f.apply(List(1, 2, 3))

当然,这是对对象 f 的方法调用 . 函数还有其他语法糖的优势:函数文字(其中两个,实际上)和 (T1, T2) => R 类型签名 . 例如:

val f = (l: List[Int]) => l mkString ""

val g: (AnyVal) => String = {

case i: Int => "Int"

case d: Double => "Double"

case o => "Other"

}

方法和函数之间的另一个相似之处是前者可以很容易地转换为后者:

val f = m _

Scala将扩展它,假设 m 类型是 (List[Int])AnyRef into(Scala 2.7):

val f = new AnyRef with Function1[List[Int], AnyRef] {

def apply(x$1: List[Int]) = this.m(x$1)

}

在Scala 2.8上,它实际上使用 AbstractFunction1 类来减少类的大小 .

请注意,无法转换其他方式 - 从函数到方法 .

然而,方法有一个很大的优点(好吧,两个 - 它们可以稍快一点):它们可以接收类型参数 . 例如,虽然上面的 f 必须指定它接收的 List 的类型(在示例中为 List[Int] ), m 可以对其进行参数化:

def m[T](l: List[T]): String = l mkString ""

我认为这几乎涵盖了一切,但我很乐意补充这可以回答任何可能存在的问题 .

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值