【在主画面加入捷径】
       
【选择语系】
繁中 简中

[Groovy] 程序设计教学:撰写和使用函式 (Function)

【赞助商连结】

    在 Java 中,函式 (function) 一定要包在类中,所以才会出现静态函式这种和物件无关但又存在于类中的函式。在 Groovy 中,这个限制放寛了,我们可以在 Groovy 中直接撰写顶层函式,Groovy 会帮我们自动转为对应的 Java函数,不需要人为介入。

    ##函数 (Function) 是什么

    函式是一种程序抽象化 (procedure abstraction) 的语法特性,其用途在包住一段程序代码,将其使用有意义的名称包装起来,之后我们要调用这段程序代码时,就可以直接透过函式名称调用 (call) 该函式,不用重覆撰写相同的程序代码。函式的伪代码如下:

    return-type fn(param_a, param_b, param_c) {
        // Implement some code here.
    }
    

    由此可知,函式有以下要件:

    *函数名称 *函数的参数 (parameters):零到多个 *函数的回传值 (returning value):零到一个 *函数本体,即实现细节

    数学上的函式比较纯粹 (pure),都是在进行运算。但电脑程序的函式依其作用分为两种:

    • 运算 (computing)
    • 状态 (state) 改变

    第一种函式比较接近数学上的函式,像 Math.sqrt 计算某个数字的平方根;第二种函式则会改变程序的状态,像是在终端机上印出文字、改变物件的属性等。撰写函式的原则是同一个函式尽量不要同时具有两种作用,将进行运算的函式和状态改变的函式分开来实现。

    注:在函数式程序设计中,将状态改变称为副作用 (side effects)。

    声明和使用函式

    以下简例声明一个函式,并调用之:

    // Declare a function.
    void hello() {
        println "Hello World"
    }
    
    // Call the function.
    hello()

    这个函式没有参数也没什回传值,在实务上这类函式用途较少,本例仅用来展示如何建立函式。

    带有参数或回传值的函式

    以下简例建立一个带有参数和回传值的函式:

    int add(int a, int b) {
        return a + b
    }
    
    assert add(3, 5) == 8

    大部分函式都会有参数,让我们调整函式的行为。此外,用来进行运算的函式也会有回传值。

    设置函式的默认值 (Default Value)

    Groovy 的函式可以加入默认值,如下例:

    String greet(name = "World") {
        "Hello ${name}"
    }
    
    assert greet() == "Hello World"
    assert greet("Michael") == "Hello Michael"

    默认值会在没有其他值时自动代入。

    递归 (Recursion)函数

    递归函式在函式中可调用自己,其用意为将问题逐渐缩小。递归函式包括两个要素:

    • 终止条件
    • 递移步骤

    在练习递归函式时,通常是没有掌握好这两个要素,造成函式无法收敛。

    费波那西数是一个常见的递归程序范例:

    int fib(int n) {
        if (n <= 1) {
            return n
        }
        
        fib(n - 1) + fib(n - 2)
    }
    
    println fib(10)

    要写好递归程序,要有明确的终止条件和递移步骤。由于递归程序在程序设计中时常见且重要的主题,最好还是花一些时间练习。

    TAGS: GROOVY, JAVA