Scala“def”方法声明:冒号vs等于

时间:2014-10-31 08:12:46

标签: function scala methods scalastyle

我正处于学习Scala的早期阶段,并且我注意到了声明方法的不同方法。

我已经确定不使用等号使方法成为 void 方法(返回Unit而不是值),并使用等号返回实际值价值如此

def product(x: Int, y: Int) {
  x*y
}

将返回()(单位),但

def product(x: Int, y: Int) = {
  x*y
}

将返回两个参数(x*y

的乘积

我注意到了第三种声明方法的方式 - 使用冒号。这是一个例子

def isEqual(x: Any): Boolean

这与=符号有何不同?在什么情况下最好用这种方式?

6 个答案:

答案 0 :(得分:11)

当你使用冒号(并使用相等)时,你明确定义方法的返回类型。

// method return Boolean value
def m(a : Int) : Boolean = a > 0 

当你不使用冒号并且使用相等时,你允许scala编译器推断返回类型本身。

// method has return type of last expression (Boolean)
def m(a : Int) = a > 0 

当你既不使用冒号也不等于你的方法时,返回类型为Unit类。

// method has Unit return type
def m(a : Int){ 
    a > 0 
}

答案 1 :(得分:1)

如果您不想要返回类型,则使用

scala> def product(x: Int, y: Int) { //in lack of = it explicit uses Unit 
     |   x*y
     | }
product: (x: Int, y: Int)Unit
//equivalent to below
scala> def product(x: Int, y: Int):Unit={ 
     |   x*y
     | }
product: (x: Int, y: Int)Unit

当你写

scala> def product(x: Int, y: Int) = {  //here it explicit detect return type
     |   x*y
     | }
product: (x: Int, y: Int)Int
//equivalent to below
scala> def product(x: Int, y: Int):Int = {
     |   return x*y
     | }
product: (x: Int, y: Int)Int

答案 2 :(得分:1)

其他人已经完美地解释了不同声明之间的差异:

def foo: Boolean = true // explicitly declare the return type

def foo = true // let the compiler to implicitly infer Boolean

话虽如此,我必须警告你反对

def foo { }

这称为过程语法,你永远不应该使用它,因为它已经already deprecated(自2013年10月29日起),尽管你只会得到一个弃用警告-Xfuture标志。

每当你必须声明一个返回Unit的方法时(你应该尽可能避免,因为这意味着你依赖于副作用),请使用以下语法

def foo: Unit = { }

此外,作为个人建议,明确注释返回类型会使您的代码更具可读性,并帮助您尽早发现错误。你知道函数应该返回什么,所以显式地注释该类型允许编译器检查实现返回一个适当的值,就在声明位置(如果你使用该函数,你最终会捕获一个错误,但也许远离错误确实是。)

此外,在声明抽象成员时,您最好还注释类型

trait {
  def foo
}

是合法的,但foo的类型会自动推断为Unit,这几乎不是您想要的。

相反,做

trait {
  def foo: Boolean
}

答案 3 :(得分:0)

def foo(arg) { sideEffects() }相当于def foo(arg) = { sideEffects(); Unit }。这是不好的风格,因为它隐藏了你的意图。 (很容易忽略丢失的=)。我建议你不要使用它。

def foo(arg) = { expression }是一个隐式解析为表达式类型的方法,是一种很好的风格。

def foo(arg): Type是一个带有显式类型的抽象方法定义。它与其他两个示例不同,因为没有提供实现。

答案 4 :(得分:0)

1)来自scala-2.11的procedure syntaxdeprecated,请避开它​​。

def product(x: Int, y: Int) {
    x*y
}
// It always returns Unit. 
// creates confusion for most beginners. deprecated for good.

2)type inference语法,主要用于小/私有方法。

def product(x: Int, y: Int) = {
    x*y
}

这是编译器的帮助,但有时编译器的推断可能与您的想法不同。

3)type annotation语法。

def product(x: Int, y: Int): Int = {
    x*y
}

对于公共API,最好明确指定返回类型。

在某些情况下,必须指定返回类型。 例如:

  • 定义递归方法时。

  • 当编译器的推理更具体但你需要泛型返回类型(Map代替HashMap)。

  • 覆盖编译器的推断。 def getId(): Long = 1

  • 如果在方法正文中的任何位置使用return

答案 5 :(得分:0)

在Scala中,函数定义为

def product(x: Int, y: Int): Int = {
  x*y
}

但是很少有"快捷方式"可以使用

  1. 因为scala具有良好的类型推断,所以可以省略类型(除非函数是递归函数):

    def product(x: Int, y: Int) = { x*y }

  2. 一切都是表达。所以函数必须返回值。代码块的最后一行是返回值。因此,如果您使用弯曲括号{},最后一行将返回。如果函数只有一行,则不需要弯曲括号。

    def product(x: Int, y: Int) = x*y

  3. 因为一切都必须返回一个值"没有值"实际上是Unit。因此,如果您不想返回有意义的值(这意味着您会产生一些副作用),请使用Unit作为返回值:

    def product(x: Int, y: Int): Unit = x*y

  4. 使用没有等号的函数只是返回Unit的另一种方法(这也称为"过程语法":

    def product(x: Int, y: Int) { x*y }