本文的寫做的靈感主要是看了這個視頻 : Tutorial: Typeclasses in Scala with Dan Rosen html
加上查閱了相關的資料,以爲能夠寫一篇博客,再加上也好久沒寫博客了。本文的主要內容是根據參考資料express
對typeclass的解釋再加上本身的一點點理解,代碼會借(cao)鑑(xi)資料中的例子(不過代碼會稍做修改)。json
首先簡單看看維基上對於typeclass的定義:"In computer science, a type class is a type system ide
construct that supports ad hoc polymorphism." 這個「ad hoc polymorphism」(特質多態)其實也被函數
稱做函數重載或運算符重載。測試
在scala中採用typeclass模式有什麼有優勢呢?總的來講就是:代碼易擴展;代碼寫得好看。
ui
如下用到的代碼均借鑑自[2] 。spa
首先咱們來看看兩個 ADT 的定義:scala
就是定義了一個表達式ADT,還有Json ADT。
視頻
而後還有給表達式賦值的和輸出Json的兩個object :
簡單測試一下:
而後如今想添加一個功能,就是給定某個類型的對象,得到該對象的json字符串。面向對象的作法是
聲明一個JsonConvertible接口,而後讓有須要類型去繼承該接口,實現 convertToJson 方法。
如今想讓Expression類型的對象都能轉成Json類型,那麼就是每一個Expression類型都要去實現
converToJson方法。
而後咱們能夠簡單測試一下:
而後如今問題來了,咱們想保持Expression接口儘可能的輕量,不想有太多的依賴,並且若是如今又要增長
一個新的trait那麼Number、Multiply和Divide三個類又要去實現這個接口的方法。或者若是Expression是屬於
第三方的庫,沒法修改來繼承JsonConvertible怎麼辦?
這時候繼承多態不適用了,咱們要用特質多態來解決這個問題。
咱們先來看看新的write函數定義,如今咱們新加了一個helper類JsonConverter,這個類實現了
把value轉化爲Json類型的方法。而後咱們來看看如今這麼作的好處:
咱們能夠看到,如今Expression能夠保持原來的樣子,而且把Expression轉化爲Json的邏輯與
Expression的實現分開了。簡單測試一下:
so far so good。可是如今想再進一步使實現更簡潔一些,這個JsonConverter其實並不必定要
顯式的傳入,咱們能夠藉助scala的implicit來實現。
就是在原來的基礎上做些小修改,把expressionJsonConverter改成implicit,還有write函數
改成curry,conv參數改成implicit。簡單測試一下:
更進一步咱們能夠用scala中的context bound來改寫代碼。
context bound 的表達形式是 A : B,意思是在上下文中存在隱式的 B[A] 類型的對象。剛開始
接觸的時候我以爲context bound 和 view bound很像, A <% B,view bound的意思你能夠把
A看成B來用,上下文中須要存在一個A到B的隱式轉換。
ok,到此就是scala type class的簡單介紹,視頻中後面還有關於Expression和Json的重構並擴展到
Int和Tuple上,有興趣的能夠看看。
相關資料
[1] What are type classes in Scala useful for?
[2] Tutorial: Typeclasses in Scala with Dan Rosen
[3] The Neophyte's Guide to Scala Part 12: Type Classes
[4] Type class