scala中普通函数定义大约有下面几种方式,

def foo1 = "foo"
def foo2() = "foo"
def foo3():String = "foo"
def foo4() {"foo"}
def foo5(str: String): String = {
 str.toUpperCase
}

scala函数定义是可以不指定返回类型的,如上面的foo1、foo2,scala会通过type inference来推导具体返回类型。仔细看foo1、foo2发现两者的区别只在于函数名称后有无(),这个差别体现在函数调用时,

foo1
foo1() // error
foo2   // works fine
foo2()

如果定义函数时不加(),那在函数调用时就只能通过名字调用。反之在调用时可以省略()。可能这个特性可以略微解释为什么scala类的默认访问权限是public。

// original
class Foo(var name: String)
val foo = new Foo("foo")
println(foo.name)       // foo
foo.name = "modified"  
println(foo.name)       // modified

// updated
class Foo(private var _name: String) {
 def name = _name
 def name_=(value: String) = _name = value
}
val foo = new Foo("foo")
println(foo.name)       // foo
foo.name = "modified"  
println(foo.name)       // modified

java提倡将field设为private并提供getter、setter用于访问,scala没有保留这一点让我初始觉得很疑惑,但从上面的代码片段可以看出,scala可以在调用代码不变的情况下对原有类进行升级修改,从这点来看public并无不可,调用方代码是无法区分究竟是直接访问值还是进行了函数调用。

不用指定函数定义返回类型在某些情况下有好处,如简单匿名函数,但当函数体不那么简单时就增加了阅读难度。因此除了匿名函数这种,最好在函数定义时都加上返回类型声明。函数定义一个可能出现的问题是上面foo4的定义,在foo4后面直接跟了{},没有指明返回类型、也没有=,在这种情况下scala会认为这函数的返回类型是Unit(类似java void)。写代码的时候好几次都忘记了这点导致了一些错误,觉得Scala就应该禁止掉这种定义方式,至少目前没看出有什么好处。

scala也支持默认参数与变长参数,

def foo(v:String = "foo") = "bar"
println(foo()) // bar

def foo(a:String, b:String = "world") = a + " " + b
println(foo("hello")) // hello world

def foo(v: String*) = {
 v.foreach(println)
}
foo("a", "b", "c") // a, b,
foo(Array("a", "b", "c"): _*)

不过在变长参数函数调用上和java有些区别,scala的变长参数函数无法直接丢进一个array,如上面代码需要在后面加上:_*才行,这种奇怪的符号还是挺难记忆的..

scala函数还支持按参数名调用,类似python,如,

 // scala
 def foo(a: String, b: String) = a + " " + b
 foo("hello", "world") // hello world
 foo(a = "hello", b = "world") // hello world
 foo("hello", b = "world") // hello world
 foo("world", a = "hello") // error
// python
def foo(a, b):
 print a, b
foo("hello", "world") // hello world
foo("hello", b = "world") // hello world
foo("world", a = "hello") // error

不过并没有怎么写过python代码,所以对这个特性带来的好处没有太多理解。此外scala也支持定义局部函数,如,

def foo(a:String) = {
 def bar(b:String) = b.toUpperCase
 bar(a)
}
foo("hello") // HELLO

综上,scala函数上从动态语言借鉴了不少东西,灵活性上比java强不少,而且还有很多相关内容还没提到..