scala 上下文界定

2021-08-24 18:11:30 字數 3989 閱讀 2572

先看乙個傳統的隱式轉換方法實現 

/** 上下文界定

* author: leisu

* date 2018/8/15 17:36

*/implicit def agecondition(person: poet) = person.age > 18

val cb = new contextbounds

val list: list[poet] = list(new poet("李白", 35),

new poet("白居易", 19),

new poet("蘇軾", 34),

new poet("辛棄疾", 17),

new poet("杜甫", 21),

new poet("張良", 18)

) println(cb.dofilter(list))

}class contextbounds

/** * 定義乙個condition特質,包含condition方法,混入此特質的類,可以使用condition進行篩選

* * @tparam t 協變

*/trait condition[+t]

/** * 詩人類

*/case class poet(val name: string, val age: int) extends condition[poet]

可以看到,隱式傳入的引數是: agecondition,這是乙個def方法,型別為(poet => boolean),是((t<: condition)=> boolean)的子類,所以可以隱式傳入。在呼叫時,只顯式傳入類第乙個引數,具體呼叫為:cb.dofilter(list),就可以成功。

呼叫後的輸出為:

list(poet(李白,35), poet(白居易,19), poet(蘇軾,34), poet(杜甫,21))
起到了過濾的效果

我們對上面對例子進行初步改變

/** 上下文界定

* author: leisu

* date 2018/8/15 17:36

*/implicit def agecondition(person: poet) = person.age > 18

val cb = new contextbounds

val list: list[poet] = list(new poet("李白", 35),

new poet("白居易", 19),

new poet("蘇軾", 34),

new poet("辛棄疾", 17),

new poet("杜甫", 21),

new poet("張良", 18)

) println(cb.dofilter(list))

}class contextbounds

/** * 定義乙個condition特質,包含condition方法,混入此特質的類,可以使用condition進行篩選

* * @tparam t 協變

*/trait condition[+t]

/** * 詩人類

*/case class poet(val name: string, val age: int) extends condition[poet]

在這個改動版本中,我們其他地方都沒變,只有class contextbounds類的 dofilter方法進行類變化:

def dofilter[t <: condition[t]](data: list[t])(implicit condition: t => boolean): list[t] =

data.filter(_.judge(implicitly[t => boolean])) //*** 注意這裡的改動

def implicitly[t](implicit t: t) = t

它的作用只是將乙個隱式轉換傳入作用域內,好讓下面的implicitly[t => boolean]能查詢到已定義好的隱式轉換。

上面例子中,我們發現了:方法定義的隱式引數入參名不重要,因為函式實體內不直接呼叫此引數名,它只是乙個宣告。這就給了我們再次優化的可能。scala對引入隱式型別有乙個新的語法,也就是:上下文界定。例子如下

/**

* 封裝原方法的類,可以看到這裡有乙個型別引數u,並且我們的方法帶上型別引數,可用度更加廣了

*/abstract class myfunctionclass[u]

/** 上下文界定

* author: leisu

* date 2018/8/15 17:36

*//**** 改動一: 這裡封裝了下原先的方法,把它放到了myfunctionclass類之下

* 因為上下文引入必須是帶有乙個型別引數的類的例項

* 雖然原先的方法時function1[poet, boolean]的例項,但無法再給它加其他型別引數,所以封裝*/

implicit val agecondition: myfunctionclass[poet] = new myfunctionclass[poet] ;

val cb = new contextbounds

val list: list[poet] = list(new poet("李白", 35),

new poet("白居易", 19),

new poet("蘇軾", 34),

new poet("辛棄疾", 17),

new poet("杜甫", 21),

new poet("張良", 18)

) println("完全上下界實現:" + cb.dofilter(list))

}class contextbounds

/** * 定義乙個condition特質,包含condition方法,混入此特質的類,可以使用condition進行篩選

* * @tparam t 協變

*/trait condition[t]

/** * 詩人類

*/case class poet(val name: string, val age: int) extends condition[poet]

這裡我們有幾個改動:

定義了乙個新類: myfunctionclass[t],其中含有乙個型別引數t。這個類是為了封裝我們之前定義的(poet => boolean)方法。之所以定義這個類,是與上下文界定的語法有關的: 上下文界定語法要求傳入有乙個型別引數的類的例項。雖然說(poet => boolean)也是function[poet, boolean]的例項,但是它沒法再有乙個型別引數,所以我這裡採用了封裝的思想,專門定義了myfunctionclass類,用來傳參。

在object contextbounds中,我宣告了這個類的實現:implicit val agecondition: myfunctionclass[poet],並且定義它為隱式轉換。這樣,這個agecondition就可以載入到其他需要此型別的隱式引數中了。

對於原先傳入隱式引數的dofilter方法,我們現在做如下定義:

def dofilter[t: myfunctionclass](data: list[t]): list[t] = data.filter(implicitly[myfunctionclass[t]].myfunction(_))

這裡可以看到並沒有像之前那樣,再方法體上直接傳入隱式入參(implicit condition ...), 那是如何生效的呢?注意看之前的型別引數那裡,這裡的定義方法為[t: myfunctionclass],這一步宣告有兩個效果:

這樣整個通過上下文界定實現傳入隱式引數的功能就全部實現。最後執行的效果為:

完全上下界實現:list(poet(李白,35), poet(白居易,19), poet(蘇軾,34), poet(杜甫,21))
可以看到與之前的結果相同

上下文 上下文棧

全域性 函式 區域性 在執行全域性 前將window確定為全域性執行上下文 對全域性資料進行預處理 var定義的全域性變數 undefined,新增為window的屬性 function宣告的全域性函式 賦值 fun 新增為window的方法 this 賦值 window 開始執行全域性 在呼叫函式...

中斷上下文 程序上下文

在學習與作業系統相關的知識時候,我們經常遇到程序上下文 中斷上下文,看似熟悉又感覺不是特別清晰。這裡我們從如下幾個方面進行描述。上下文是從英文中context翻譯過來的,指的是一種環境。上下文我們看起來不怎麼熟悉,但是我們可以看context的中文翻譯,或者我們能更加的情形些。context n 語...

全域性上下文與上下文

全域性上下文由main函式載入系統的主架構和主事件迴圈和全域性資料構成。是上帝創造世界時,建立的基礎事物。萬物之始,大道至簡,衍化至繁。全域性上下文代表著程式執行所需要的基礎資源。是程式執行的基礎。全域性上下文的特徵是在程式執行期間常駐記憶體。全域性上下文的生命週期和應用程式的生命週期相同。與應用程...