我正处于学习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
这与=
符号有何不同?在什么情况下最好用这种方式?
答案 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 syntax
为deprecated,请避开它。
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
}
但是很少有"快捷方式"可以使用
因为scala具有良好的类型推断,所以可以省略类型(除非函数是递归函数):
def product(x: Int, y: Int) = {
x*y
}
一切都是表达。所以函数必须返回值。代码块的最后一行是返回值。因此,如果您使用弯曲括号{},最后一行将返回。如果函数只有一行,则不需要弯曲括号。
def product(x: Int, y: Int) = x*y
因为一切都必须返回一个值"没有值"实际上是Unit
。因此,如果您不想返回有意义的值(这意味着您会产生一些副作用),请使用Unit作为返回值:
def product(x: Int, y: Int): Unit = x*y
使用没有等号的函数只是返回Unit的另一种方法(这也称为"过程语法":
def product(x: Int, y: Int) { x*y }