Function 斯卡拉“;def";方法声明:冒号vs等于

Function 斯卡拉“;def";方法声明:冒号vs等于,function,scala,methods,scalastyle,Function,Scala,Methods,Scalastyle,我正处于学习Scala的早期阶段,我注意到了声明方法的不同方法 def product(x: Int, y: Int) = { x*y } 我已经确定,不使用等号会使该方法成为无效方法(返回一个单位而不是一个值),而使用等号会返回实际值,因此 def product(x: Int, y: Int) { x*y } 将返回()(单位),但 将返回两个参数的乘积(x*y) 我注意到了声明方法的第三种方法——冒号。这里有一个例子 def isEqual(x: Any): Boolean

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

def product(x: Int, y: Int) = {
    x*y
}
我已经确定,不使用等号会使该方法成为无效方法(返回一个
单位而不是一个值),而使用等号会返回实际值,因此

def product(x: Int, y: Int) {
  x*y
}
将返回
()
(单位),但

将返回两个参数的乘积(
x*y

我注意到了声明方法的第三种方法——冒号。这里有一个例子

def isEqual(x: Any): Boolean
这与
=
符号有何不同?在什么情况下最好使用这种方法?

当您使用冒号(并使用equal)时,您会显式地定义方法的返回类型

// method return Boolean value
def m(a : Int) : Boolean = a > 0 
如果不使用冒号和equal,则允许scala编译器推断返回类型本身

// method has return type of last expression (Boolean)
def m(a : Int) = a > 0 
如果既不使用冒号也不使用equal,则方法的返回类型为Unit类

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

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

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
def foo(arg){sideEffects()}
相当于
def foo(arg)={sideEffects();Unit}
。这是一种糟糕的风格,因为它隐藏了你的意图。(很容易忽略缺少的
=
)。我建议你不要用它

def foo(arg)={expression}
是一种隐式解析表达式类型的方法,是一种良好的样式


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

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

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

话虽如此,我必须警告你

def foo { }
这就是所谓的过程语法,您永远不应该使用它,因为它一直都是(从2013年10月29日起),尽管您只会在
-Xfuture
标志下收到弃用警告

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

def foo: Unit = { }

此外,作为个人建议,显式注释返回类型通常会使代码更具可读性,并帮助您尽早捕获错误。您知道函数应该返回什么,因此显式注释类型允许编译器检查实现是否在声明位置返回适当的值(如果使用函数,您最终将捕获错误,但可能与错误的实际位置相差很远)

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

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

相反,你应该这样做

trait {
  def foo: Boolean
}
1)
过程语法来自scala-2.11,请避免使用它

def product(x: Int, y: Int) {
    x*y
}
// It always returns Unit. 
// creates confusion for most beginners. deprecated for good.
2)
类型推断
语法,主要用于小型/私有方法

def product(x: Int, y: Int) = {
    x*y
}
这是编译器的帮助,但有时编译器的推断可能与您的想法不同

3)
类型注释
语法

def product(x: Int, y: Int): Int = {
    x*y
}
对于公共API,显式指定返回类型是一种良好的做法

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

  • 定义递归方法时

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

  • 重写编译器的推理
    def getId():Long=1

  • 如果
    返回
    在方法体中的任何位置使用


    • 在Scala中,函数定义为

      def product(x: Int, y: Int): Int = {
        x*y
      }
      
      但可以使用的“捷径”很少

    • 由于scala具有良好的类型推断,因此可以省略该类型(除非函数为递归函数):

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

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

      def产品(x:Int,y:Int)=x*y

    • 因为所有东西都必须返回一个值,“无值”实际上是
      单位
      。因此,如果您不想返回有意义的值(这意味着您会产生一些副作用),请使用单位作为返回值:

      def产品(x:Int,y:Int):单位=x*y

    • 使用不带等号的函数只是返回单位的另一种方式(也称为“过程语法”:

      def产品(x:Int,y:Int){x*y}

      • 请注意,应避免使用和

    • 仅供参考,虽然许多答案正确地指出,args的关闭
      和方法体的打开
      {
      之间的过程语法(没有
      =
      )被(无声地)弃用,但并非每个人都认为
      =
      是“容易忽略的”.就我个人而言,与返回有用信息的方法相比,
      :Unit=
      很容易被忽略;它不会让我觉得它肯定会产生副作用。也就是说,no equals语法应该最终消失,所以最好不要太喜欢它。
      def product(x: Int, y: Int): Int = {
        x*y
      }