Scala泛型

来源:https://www.cnblogs.com/paopaoT/archive/2023/06/21/17497246.html
-Advertisement-
Play Games

# 泛型的定義 ```Scala object _11_泛型 { def main(args: Array[String]): Unit = { //[A] 這個代表的就是泛型 ==》 在創建對象的時候,可以指定需要傳進去的類型 //作用就是在創建對象的時候,可以對傳進去的參數一個約束,當設置泛型位 ...


泛型的定義

object _11_泛型 {
  def main(args: Array[String]): Unit = {
    //[A]  這個代表的就是泛型  ==》 在創建對象的時候,可以指定需要傳進去的類型
    //作用就是在創建對象的時候,可以對傳進去的參數一個約束,當設置泛型位int之後,那麼傳進去的值就必須是int
    //apply[A](xs: A*): List[A] = xs.toList
    val ints: List[Int] = List[Int](1, 2, 3, 4)

    //自己寫一個?  單純演示泛型語法的定義,沒有什麼實際的意義
    /**
     * 將泛型定義在類上,那麼在整個類中,都可以使用該泛型,作用域是整個類
     * @tparam T
     */
    class TestFanXin[T](){
      def max(a:T,b:T)= a
    }
    //如果設置泛型位Int類型,那麼方法的參數就只能傳Int類型
    new TestFanXin[Int]().max(1,2)
    //如果設置泛型位String類型,那麼方法的參數就只能傳String類型
    new TestFanXin[String]().max("aa","bb")

    /**
     * 泛型也可以定義在方法上,如果定義在方法上,那麼該泛型的作用域只能作用在該方法中
     * 出了該方法便不能生效
     */
    class TestFanXin1(){
      def max[T](a:T,b:T)= a
      def min[A](a:A,b:A)= b
    }
  }
}

泛型上下限

泛型的上下限的作用是對傳入的泛型進行限定。
語法:

//泛型上限  只能夠傳Person 這個類和他的的子類
Class PersonList[T <: Person]{ 
}
//泛型下限 只能夠傳Person 這個類和他的的父類
Class PersonList[T >: Person]{ 
}

代碼示例:

package com.doit.day02


object _12_泛型的上下限 {
  def main(args: Array[String]): Unit = {

    def sayHi[A <: Father](a:A): Unit ={
      println("test")
    }

    def sayHello[A >: Father](a:A): Unit ={
      println("test")
    }

    //調用sayHi的時候,傳進去的參數因為有泛型的上界約定,所以只能傳入Father和Father的子類
    sayHi(new Son())
    sayHi(new Father())
    //這邊編譯的時候雖然不報錯,但是運行的時候會報錯
//    sayHi(new GrandFather())

    //如果泛型是定義在方法上的,如果沒有加泛型,是限制不住的,但是加了泛型,還是可以限制住的
//    sayHello[ABC](new ABC)
//    sayHello[Son](new Son)
    sayHello(new Father)
    sayHello(new GrandFather)


    class Test[A >:Father]{
      def sayHi(a:A) ={
        println("hello")
      }
    }

    new Test[Father].sayHi(new Father)
    //如果定義在類上的話,就能約束住了
//    new Test[Son].sayHi(new Son)
    new Test[GrandFather].sayHi(new GrandFather)




  }
}

class Son extends Father

class Father extends GrandFather

class GrandFather

class ABC

視圖限定

約束本質:存在一個隱式轉換,能夠將T類型轉換成B類型
泛型視圖限定:T <% B

package com.doit.day02

object _13_視圖限定 {
  def main(args: Array[String]): Unit = {

    class Bird(val name:String){
      def fly()={println(name + "飛走了")}
    }

    class ToyBird

    def bitBird[T <% Bird](b:T)=b.fly()

    bitBird[Bird](new Bird("小鳥"))

    implicit def toy2Bird(toyBird: ToyBird)= new Bird("玩具鳥")

    bitBird[ToyBird](new ToyBird)
  }
}

上下文限定

上下文限定是將泛型和隱式轉換的結合產物,以下兩者功能相同,使用上下文限定[A : Ordering]之後,方法內無法使用隱式參數名調用隱式參數,需要通過 implicitly[Ordering[A]]獲取隱式變數,如果此時無法查找到對應類型的隱式變數,會發生出錯誤。

implicit val x = 1
val y = implicitly[Int]
val z = implicitly[Double]

語法:

def f[A : B](a: A) = println(a) 
//等同於 def f[A](a:A)(implicit arg:B[A])=println(a)```
代碼示例:
```Scala
package com.doit.day02

object _14_上下文界定 {
  def main(args: Array[String]): Unit = {

    /**
     * 泛型的上下文界定
     */

    case class Tiger(age:Int,weight:Int)
    case class Cat(age:Int,weight:Int)
    //我想比較兩個老虎的大小  單純的老虎,沒有實現compare方法的話,是沒有辦法調用compare來比較的
    //兩個辦法,第一個辦法,在類上實現Ordered 特質,重寫 compareTo方法
    //第二個方法,傳一個比較器進去,這樣他們就可以用比較器來比較了
    def bigger(tiger: Tiger,tiger1:Tiger,cmp:Ordering[Tiger]):Tiger={
      if (cmp.compare(tiger,tiger1)> 0) tiger else tiger1
    }

    //上面這種方法確實是可以比較,但是只能比較老虎,我想比較個貓好像就比較不了了
    //想比較貓,得重新在寫一個
    def bigger1(cat: Cat,cat1:Cat,cmp:Ordering[Cat]):Cat={
      if (cmp.compare(cat,cat1)> 0) cat else cat1
    }

    //不過回頭想比較狗狗,又要寫一個,比較麻煩,不通用
    //這時候就可以定義泛型了
    def bigger2[T](t: T,t1:T,cmp:Ordering[T]):T={
      if (cmp.compare(t,t1)> 0) t else t1
    }

    //方法的調用  這樣是沒什麼問題的
    //但是在馬大爺眼裡,這麼寫代碼,多low啊,不符合馬大爺的氣質,他就開始搞事情了
    bigger2[Cat](Cat(10,100),Cat(20,80),new Ordering[Cat] {
      override def compare(x: Cat, y: Cat) = x.age - y.age
    })

    //咱們不是有隱式轉換嘛,能不能把這個比較器呢?
    //我上下文中找找,有沒有什麼隱式的比較器可以拿過來用,如果有我就直接拿過來,這樣就不用傳比較器了,去偷一個不香嘛
    //bigger3[T :Ordering]  註意:如果想讓他自己偷一個,那麼需要實現上下文界定,不然是沒辦法使用的
    def bigger3[T :Ordering](t: T,t1:T):T={
      if(implicitly[Ordering[T]].compare(t,t1)>0) t else t1
    }

    /**
     * 兩種創建隱式比較器對象的寫法
     */
    //    implicit val value: Ordering[Cat] = new Ordering[Cat] {
//      override def compare(x: Cat, y: Cat) = x.age - y.age
//    }

    implicit val value1 = Ordering.by[Cat,Int](cat=>cat.age)

    bigger3[Cat](Cat(10,100),Cat(20,80))
  }
}

逆變,協變,不變

語法:
不變:預設
協變: +T
逆變: -T

package com.doit.day02

/**
 *
 * 不變:預設
 * 協變: +T
 * 逆變: -T
 */
object _15_逆變協變不變 {
  def main(args: Array[String]): Unit = {

    class Box[T](t:T)
    class Pencil
    class YZPencil extends Pencil

    /**
     * 本身我的pencil 和YZpencil 是父子關係
     * 那麼按照常理來說,我裝筆的盒子也是圓珠筆的盒子的父類,這樣的話咱們能夠理解
     * 我盒子既然能裝筆,而且圓珠筆又是筆的父類,所以我這個盒子應該能裝圓珠筆
     * 畢竟有多態的存在,我的筆本身可以接收圓珠筆的 ==>理解 ?
     */
    val box1: Box[Pencil] = new Box[Pencil](new Pencil)
    val box2: Box[YZPencil] = new Box[YZPencil](new YZPencil)
    //但是在代碼中,卻不能這麼操作  雖然圓珠筆和筆存在父子關係,但是一旦把他們裝在盒子中,就不存在這樣的關係了
    //這種的關係我們稱他為不變
//    val box3: Box[Pencil] = new Box[YZPencil](new YZPencil)  //報錯

    //如果想讓他們依然有關係,可以的,scala給我提供了另外一種方式叫協變和逆變
    class Box1[+T](t:T)
    class Pencil1
    class YZPencil1 extends Pencil1
    //本身圓珠筆是筆的子類,加上了協變這麼一個操作  那麼裝筆的盒子就是裝圓珠筆的父類了
    val box3: Box1[Pencil1] = new Box1[YZPencil1](new YZPencil1)


    // 逆變
    //如果想讓他們依然有關係,可以的,scala給我提供了另外一種方式叫協變和逆變
    class Box2[-T](t:T)
    class Pencil2
    class YZPencil2 extends Pencil2
    //本身圓珠筆是筆的子類,加上了逆變這麼一個操作  那麼裝筆的盒子就是裝圓珠筆的子類了(父子關係顛倒過來了)
    val box4: Box2[YZPencil2] = new Box2[Pencil2](new Pencil2)

  }
}

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

-Advertisement-
Play Games
更多相關文章
  • # 關聯文章: - [MySQL對derived table的優化處理與使用限制](http://mp.weixin.qq.com/s?__biz=MzkzMTIzMDgwMg==&mid=2247501528&idx=1&sn=03ea1cd0eb8f42bacda0583879ad494c&ch ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 本文介紹了一種新的HTML元素搜索方法,並提供了一個實用的工具來幫助開發者快速找到所需的元素。這對於那些需要處理大量HTML元素的開發者來說是非常有用的。文章還通過提供一些常見元素的用法示例,幫助開發者更好地理解和應用這些元素。在眾多元素 ...
  • 前不久,在網上看到這麼一張非常有趣的圖: ![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4edc3cef70d744d381eabb604ef089cb~tplv-k3u1fbpfcp-watermark.image?) 想必很多同學都看 ...
  • Stencil 組件使用 `JSX` 渲染,這是一種流行的聲明式模板語法。每個組件都有一個渲染函數,它返回在運行時渲染到 DOM 的組件樹。 ## 基礎用法 `render` 函數用於輸出將繪製到屏幕上的組件樹。 ```ts class MyComponent { render() { return ...
  • 註冊表是Windows中的一個重要的資料庫,用於存儲系統和應用程式的設置信息,註冊表是一個巨大的樹形結構,無論在應用層還是內核層操作註冊表都有獨立的API函數可以使用,而在內核中讀寫註冊表則需要使用內核裝用API函數,如下將依次介紹並封裝一些案例,實現對註冊表的創建,刪除,更新,查詢等操作。 ...
  • 工業互聯網項目開發全流程V3.0 工業互聯網項目開發工作流程及核心問題 一、需求分析 1、共用平臺需求分析 這個平臺要解決什麼問題?這個平臺的用戶群體是誰?這個平臺應該具備哪些主要功能?這個平臺的使用場景是什麼?這個平臺如何與現有的系統集成? 2、需求文檔設計 需求文檔是否詳細、明確,且可以量化?是 ...
  • > 本文首發於公眾號:Hunter後端 > 原文鏈接:[celery筆記五之消息隊列的介紹](https://mp.weixin.qq.com/s/fw7b1Gha0XpTYuCg3aZcWA) 前面我們介紹過 task 的處理方式,將 task 發送到隊列 queue,然後 worker 從 qu ...
  • 某日二師兄參加XXX科技公司的C++工程師開發崗位第21面: > 面試官:用過STL嗎? > > 二師兄:(每天都用好嗎。。)用過一些。 > > 面試官:你知道STL是什麼? > > 二師兄:STL是指標準模板庫(`Standard Template Library`),是C++區別於C語言的特征之 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...