函數文本最大的優勢就是可以像字符串或者對象等其他文本(literal)一樣傳送它
這種特性為構建高度緊湊和可重用代碼提供無限的可能性
我們的第一個高階函數
當我們將一個函數文本傳送給一個方法的時候
我們最主要的是一個接收方法參數的方法(這個確實很繞
_
|||)
這類方法就叫做高階函數
上文Swing例子中提到的 addActionListener 方法恰好屬於這類
我們還可以定義自己的高階函數來為自己提供許多便利
讓我們看一個簡單的例子
def measure[T](func:=>T)
T {
val start = System
nanoTime()
val result = func
val elapsed = System
nanoTime()
start;
print(
The execution of this call took: %s ns
format(elapsed))
result
}
在這個例子中
我們聲明了一個名為measure的方法用來計算這個名為func的函數文本的回調所需要的時間
func 方法的簽名(signature)是它不接收任何參數並且返回一個泛型類型T
正如你所看到的
Scala中的函數並不一定需要參數盡管它們能夠
而且往往也含有參數
現在我們可以向 measure 方法中傳遞任何函數文本(或者方法)
def myCallback = {
Thread
sleep(
)
I just took a poewrnap
}
val result = measure(myCallback)
> The execution of this call took:
ns
從概念的角度講我們所做的
就是將計算方法調用時間和實際的運算區分開來
我們構造了兩塊可以重用
松散耦合
類似於攔截器(interceptor)的代碼塊(measure和myCallback)
通過高階函數實現重用
先看一個假設的例子
兩個可重用構造略緊耦合
def doWithContact(fileName:String
handle:Contact => Unit)
Unit = {
try {
val contactStr = io
Source
fromFile(fileName)
mkString
val contact = AContactParser
parse(contactStr)
handle(contact)
}
catch {
case e: IOException => println(
couldn
t load contact file:
+ e)
case e: ParseException => println(
coulnd
t parse contact file:
+ e)
}
}
doWithContact 方法從文件中讀取電子名片之類的聯系方式然後將數據提供給一個解析器(parser)將數據轉化成為聯系領域的對象
然後這個對象被傳遞給一個函數文本回調 handle
doWithContact 方法 很函數文本均返回 Unit 類型
等同於java中的返回void的方法
現在
我們可以定義各種各樣的可以傳遞給 doWithContact 的回調函數
val storeCallback = (c:Contact) => ContactDao
save(c)
val sendCallback = (c:Contact) => {
val msgBody = nvert(c)
RestService
send(msgBody)
}
val combineCallback = (c:Contact) => {
storeCallback(c)
sendCallback(c)
}
doWithContact(
custerX
vcf
storeCallback)
doWithContact(
custerY
vcf
sendCallback)
doWithContact(
custerZ
vcf
combineCallback)
doWithContact(
custerZ
vcf
combineCallback)
回調函數也可以通過內聯傳遞
doWithContact(
custerW
vcf
(c:Contact) => ContactDao
save(c))
Java
中的高階函數
java
中的等效實現看起來十分相似
使用目前的語法建議
public interface Block<T> {
void apply(T t)
}
public void doWithContact(String fileName
Block<Contact> block)
{
try {
String contacStr = FileUtils
readFileToString(new File(fileName))
Contact
apply(contact)
block
apply(contact)
}
catch (IOException e)
{
System
out
println(
cloudn
t load contact file:
+ e
getMessage())
}
catch (ParseException e)
{
System
out
println(
cloudn
t parse contact file:
+ e
getMessage())
}
}
//usage doWithContact(
custerX
vcf
c
> ContactDao
save(c)
)
使用高階函數的益處
正如你見到的
函數幫助我們干淨地將對象的創建和處理區分開來
通過這種方法
新的業務邏輯處理對象就可以輕易的添加進來而沒有必要同對象創建邏輯相耦合
結果就是
我們通過使用高階函數來使我們的代碼保持DRY(Dont
t Repeat Yourself) 因而
程序員可以從一個非常細粒度的代碼重用中獲得最佳利益
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26551.html