Scala的高級特性

来源:https://www.cnblogs.com/jifengblog/archive/2018/07/18/9326857.html
-Advertisement-
Play Games

高階函數 概念 Scala混合了面向對象和函數式的特性,我們通常將可以作為參數傳遞到方法中的表達式叫做函數。在函數式編程語言中,函數是“頭等公民”,高階函數包含:作為值的函數、匿名函數、閉包、柯里化等等。 作為值的函數 可以像任何其他數據類型一樣被傳遞和操作的函數,每當你想要給演算法傳入具體動作時這個 ...


 

 高階函數

概念

Scala混合了面向對象和函數式的特性,我們通常將可以作為參數傳遞到方法中的表達式叫做函數。在函數式編程語言中,函數是“頭等公民”,高階函數包含:作為值的函數、匿名函數、閉包、柯里化等等。

作為值的函數   

可以像任何其他數據類型一樣被傳遞和操作的函數,每當你想要給演算法傳入具體動作時這個特性就會變得非常有用。

 

 

定義函數時格式:val 變數名 (輸入參數類型和個數)  =>  函數實現和返回值類型

=”表示將函數賦給一個變數

=>”左面表示輸入參數名稱、類型和個數,右邊表示函數的實現和返回值類型

匿名函數

在Scala中,你不需要給每一個函數命名,沒有將函數賦給變數的函數叫做匿名函數。

 

 

由於Scala可以自動推斷出參數的類型,所有可以寫的跟精簡一些

 

 

還記得神奇的下劃線嗎?這才是終極方式

 

 

柯里化

什麼是柯里化

柯里化(Currying)指的是把原來接受多個參數的函數變換成接受一個參數的函數過程,並且返回接受餘下的參數且返回結果為一個新函數的技術。

 

 

 

例子

(1)     一個普通的非柯里化的函數定義,實現一個加法函數:

 

scala> def plainOldSum(x:Int,y:Int)=x+y
plainOldSum: (x: Int, y: Int)Int
 
scala> plainOldSum(1,2)
res0: Int = 3

 


(2)     使用“柯里化”技術來定義這個加法函數,原來函數使用一個參數列表,“柯里化”,把函數定義為多個參數列表: 

scala> def curriedSum(x:Int)(y:Int)=x+y
curriedSum: (x: Int)(y: Int)Int
 
scala> curriedSum(1)(2)
res1: Int = 3
 
當你調用curriedSum (1)(2)時,實際上是依次調用兩個普通函數(非柯里化函數),
第一次調用使用一個參數x,返回一個函數類型的值,
第二次使用參數y調用這個函數類型的值。

 


(3)     使用下麵兩個分開的定義在模擬curriedSum柯里化函數: 

首先定義第一個函數:
scala> def first(x:Int)=(y:Int)=>x+y
first: (x: Int)Int => Int
 
然後我們使用參數1調用這個函數來生成第二個函數:
scala> val second =first(1)
second: Int => Int = <function1>
scala> second(2)
res2: Int = 3

 


(4)     使用curriedSum 來定義second 

 

scala> val onePlus=curriedSum(1)_
onePlus: Int => Int = <function1>

 
下劃線“_” 作為第二參數列表的占位符, 這個定義的返回值為一個函數,當調用時會給調用的參數加一。
 
scala> onePlus(2)
res3: Int = 3

調用生成的函數,給函數傳入參數,即可得到我們想要的結果。

 

  

總結

scala柯里化風格的使用可以簡化主函數的複雜度,提高主函數的自閉性,提高功能上的可擴張性、靈活性。可以編寫出更加抽象,功能化和高效的函數式代碼。

閉包

什麼是閉包

閉包是一個函數,返回值依賴於聲明在函數外部的一個或多個變數。
閉包通常來講可以簡單的認為是可以訪問不在當前作用域範圍內的一個函數。

例子

package cn.itcast.closure

/**
  * scala中的閉包
  * 閉包是一個函數,返回值依賴於聲明在函數外部的一個或多個變數。
  */
object ClosureDemo {

  def main(args: Array[String]): Unit = {
       val y=10

      //變數y不處於其有效作用域時,函數還能夠對變數進行訪問
        val add=(x:Int)=>{
          x+y
        }

    //在add中有兩個變數:x和y。其中的一個x是函數的形式參數,
    //在add方法被調用時,x被賦予一個新的值。
    // 然而,y不是形式參數,而是自由變數
    println(add(5)) // 結果15
  }
}

 

 

隱式轉換和隱式參數

隱式轉換

Scala提供的隱式轉換和隱式參數功能,是非常有特色的功能。是Java等編程語言所沒有的功能。它可以允許你手動指定,將某種類型的對象轉換成其他類型的對象或者是給一個類增加方法。通過這些功能,可以實現非常強大、特殊的功能。

Scala的隱式轉換,其實最核心的就是定義隱式轉換方法,即implicit conversion function。定義的隱式轉換方法,只要在編寫的程式內引入,就會被Scala自動使用。Scala會根據隱式轉換方法的簽名,在程式中使用到隱式轉換方法接收的參數類型定義的對象時,會自動將其傳入隱式轉換方法,轉換為另外一種類型的對象並返回。這就是“隱式轉換”。其中所有的隱式值和隱式方法必須放到object中

然而使用Scala的隱式轉換是有一定的限制的,總結如下:

  • implicit關鍵字只能用來修飾方法、變數(參數)。
  • 隱式轉換的方法在當前範圍內才有效。如果隱式轉換不在當前範圍內定義(比如定義在另一個類中或包含在某個對象中),那麼必須通過import語句將其導。

隱式參數

所謂的隱式參數,指的是在函數或者方法中,定義一個用implicit修飾的參數,此時Scala會嘗試找到一個指定類型的,用implicit修飾的參數,即隱式值,並註入參數。

Scala會在兩個範圍內查找:

  • 當前作用域內可見的val或var定義的隱式變數;
  • 一種是隱式參數類型的伴生對象內的隱式值;

 

 

隱式轉換方法作用域與導入

(1)Scala預設會使用兩種隱式轉換,一種是源類型或者目標類型的伴生對象內的隱式轉換方法;一種是當前程式作用域內的可以用唯一標識符表示的隱式轉換方法。

(2)如果隱式轉換方法不在上述兩種情況下的話,那麼就必須手動使用import語法引入某個包下的隱式轉換方法,比如import test._。通常建議,僅僅在需要進行隱式轉換的地方,用import導入隱式轉換方法,這樣可以縮小隱式轉換方法的作用域,避免不需要的隱式轉換。

隱式轉換的時機

(1)當對象調用類中不存在的方法或成員時,編譯器會自動將對象進行隱式轉換

(2)當方法中的參數的類型與目標類型不一致時

 

隱式轉換和隱式參數案例

隱式轉換案例一

(讓File類具備RichFile類中的read方法)

package cn.itcast.implic_demo

import java.io.File
import scala.io.Source

object MyPredef{
  //定義隱式轉換方法
  implicit def file2RichFile(file: File)=new RichFile(file)
}

class RichFile(val f:File) {
  def read()=Source.fromFile(f).mkString
}

object RichFile{
  def main(args: Array[String]) {
    val f=new File("E://words.txt")

    //使用import導入隱式轉換方法
    import MyPredef._
    //通過隱式轉換,讓File類具備了RichFile類中的方法
    val content=f.read()
    println(content)
  }
}

 

 

隱式轉換案例二

(超人變身)

package cn.itcast.implic_demo

class Man(val name:String)
class SuperMan(val name: String) {
  def heat=print("超人打怪獸")
}

object SuperMan{
  //隱式轉換方法
  implicit def man2SuperMan(man:Man)=new SuperMan(man.name)
  def main(args: Array[String]) {
      val hero=new Man("hero")

      //Man具備了SuperMan的方法
      hero.heat
  }
}

 

隱式轉換案例三

(一個類隱式轉換成具有相同方法的多個類)

package cn.itcast.implic_demo

class A(c:C) {
    def readBook(): Unit ={
      println("A說:好書好書...")
    }
}
class B(c:C){
  def readBook(): Unit ={
    println("B說:看不懂...")
  }
  def writeBook(): Unit ={
    println("B說:不會寫...")
  }
}
class C
object AB{
  //創建一個類的2個類的隱式轉換
  implicit def C2A(c:C)=new A(c)
  implicit def C2B(c:C)=new B(c)
}

object B{
  def main(args: Array[String]) {
    //導包
    //1. import AB._ 會將AB類下的所有隱式轉換導進來
    //2. import AB._C2A 只導入C類到A類的的隱式轉換方法
    //3. import AB._C2B 只導入C類到B類的的隱式轉換方法
    import AB._
    val c=new C
    //由於A類與B類中都有readBook(),只能導入其中一個,否則調用共同方法時代碼報錯
    //c.readBook()
    //C類可以執行B類中的writeBook()
    c.writeBook()
  }
}

 



隱式參數案例四

(員工領取薪水)

package cn.itcast.implic_demo

object Company{
  //在object中定義隱式值    註意:同一類型的隱式值只允許出現一次,否則會報錯
  implicit  val aaa="zhangsan"
  implicit  val bbb=10000.00
}

class Boss {
  //註意參數匹配的類型   它需要的是String類型的隱式值
  def callName()(implicit name:String):String={
    name+" is coming !"
  }

  //定義一個用implicit修飾的參數
  //註意參數匹配的類型    它需要的是Double類型的隱式值
  def getMoney()(implicit money:Double):String={
   " 當月薪水:"+money
  }
}

object Boss extends App{
  //使用import導入定義好的隱式值,註意:必須先載入否則會報錯
  import Company._
  val boss =new Boss
  println(boss.callName()+boss.getMoney())
}

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、引入 之前一個離職的同事負責的項目大量的引入了AngularJS的JS框架,後來我接手相關他項目里的功能。由於對AngularJS不是太熟,在他的功能上進行二次開發就比較費勁了,印象比較深的一個就是如何創建並初始化一個Select選擇框。最近我又研究了一下AngularJS,研究出一個個人覺得比 ...
  • 緩存是分散式系統中的重要組件,主要解決高併發,大數據場景下,熱點數據訪問的性能問題。提供高性能的數據快速訪問。 一、緩存概述 緩存是分散式系統中的重要組件,主要解決高併發,大數據場景下,熱點數據訪問的性能問題。提供高性能的數據快速訪問。 1.1緩存的原理 (1) 將數據寫入/讀取速度更快的存儲(設備 ...
  • 01 基礎加強六天02 資料庫四天03 SQL和ADO三天04 JavaScript05 DOM06 JQuery07 .NET就業班-三層項目+SVN五天08 ASP.NET十一天09 圖書商城項目五天10 EF11 MVC兩天12 OA項目九天13 就業培訓14 win10APP開發15 Uni ...
  • Description 根據一些書上的記載,上帝的一次失敗的創世經歷是這樣的: 第一天, 上帝創造了一個世界的基本元素,稱做“元”。 第二天, 上帝創造了一個新的元素,稱作“α”。“α”被定義為“元”構成的集合。容易發現,一共有兩種不同的“α”。 第三天, 上帝又創造了一個新的元素,稱作“β”。“β ...
  • python3中str預設為Unicode的編碼格式 Unicode是一32位編碼格式,不適合用來傳輸和存儲,所以必須轉換成utf-8,gbk等等 所以在Python3中必須將str類型轉換成bytes類型的 在Python中使用encode的方式可以進行字元的編碼 實際用法: >>>a = "中國 ...
  • 半夜整理東西,發現一個以前沒留意到的小問題。 PHP 7.0+ 里支持了函數(和方法)的返回值類型提示,上述第二種寫法在解釋運行時會觸發一個 Fatal Error,要求返回值必須是 integer 類的一個實例: 當然,兩者在強制類型轉換時效果是一樣的: 相關鏈接 PHP difference b ...
  • 使用工具(可點擊下載) Microsoft HTML HELP javadoc2html 上述軟體基於Windows系統,javadoc2chm安裝過程中系統會檢測HTML HELP是否存在。簡單地下載安裝即可。 材料:jdk官方文檔 到oracle官網下載一個叫jdk-xuyyy-docs-all ...
  • Hibernate框架第一天 今天任務 教學導航 框架和CRM項目的整體介紹 Hibernate框架的學習路線 案例一:完成客戶的CRUD的操作 需求分析 技術分析之Hibernate框架的概述 Hibernate框架的概述 什麼是ORM(對象關係映射) Hibernate優點 技術分析之Hiber ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...