8. Scala面向對象編程(高級部分)

来源:https://www.cnblogs.com/zhanghuicheng/archive/2019/05/05/10800424.html
-Advertisement-
Play Games

8.1 靜態屬性和靜態方法 8.1.1 靜態屬性-提出問題 有一群小孩在玩堆雪人,不時有新的小孩加入,請問如何知道現在共有多少人在玩?請使用面向對象的思想,編寫程式解決 8.1.2 基本介紹 -Scala中靜態的概念-伴生對象 Scala語言是完全面向對象(萬物皆對象)的語言,所以並沒有靜態的操作( ...


8.1 靜態屬性和靜態方法

  8.1.1 靜態屬性-提出問題 

      有一群小孩在玩堆雪人,不時有新的小孩加入,請問如何知道現在共有多少人在玩?請使用面向對象的思想,編寫程式解決

      小孩堆雪人

  8.1.2 基本介紹

      -Scala中靜態的概念-伴生對象

        Scala語言是完全面向對象(萬物皆對象)的語言,所以並沒有靜態的操作(即在Scala中沒有靜態的概念)。但是為了能夠和Java語言交互(因為Java中有靜態概念),就產生了一種特殊的對象來模擬類對象,我們稱之為類的伴生對象。這個類的所有靜態內容都可以放置在它的伴生對象中聲明和調用

  8.1.3 伴生對象的快速入門 

object boke_demo01 {

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

    println(ScalaPerson.sex) //true 在底層等價於 ScalaPerson$.MODULE$.sex()
    ScalaPerson.sayHi() //在底層等價於 ScalaPerson$.MODULE$.sayHi()
  }
}

//說明
//1. 當在同一個文件中,有 class ScalaPerson 和 object ScalaPerson
//2. class ScalaPerson 稱為伴生類,將非靜態的內容寫到該類中
//3. object ScalaPerson 稱為伴生對象,將靜態的內容寫入到該對象(類)
//4. class ScalaPerson 編譯後底層生成 ScalaPerson類 ScalaPerson.class
//5. object ScalaPerson 編譯後底層生成 ScalaPerson$類 ScalaPerson$.class
//6. 對於伴生對象的內容,我們可以直接通過 ScalaPerson.屬性 或者方法

//伴生類
class ScalaPerson { //
  var name: String = _
}

//伴生對象
object ScalaPerson { //
  var sex: Boolean = true

  def sayHi(): Unit = {
    println("object ScalaPerson sayHI~~")
  }
}

      -對快速入門的案例的源碼分析

      源碼分析

  8.1.4 伴生對象的小結 

      1) Scala中伴生對象採用object關鍵字聲明,伴生對象中聲明的全是“靜態”內容,可以通過伴生對象名稱直接調用

      2) 伴生對象對應的類稱之為伴生類,伴生對象的名稱應該和伴生類名一致

      3) 伴生對象中的屬性和方法都可以通過伴生對象名(類名)直接調用訪問

      4) 從語法角度來講,所謂的伴生對象其實就是類的靜態方法和成員的集合

      5) 從技術角度來講,Scala還是沒有生成靜態的內容,只不過是將伴生對象生成了一個新的類,實現屬性和方法調用[反編譯看源碼]

      6) 從底層原理看,伴生對象實現靜態特性是依賴 public static final MOUDLE$ 實現的

      7) 伴生對象的聲明應該和伴生類的聲明在同一個源碼文件中(如果不在同一個文件中會運行錯誤),但是如果沒有伴生類,也就沒有所謂的伴生對象了,所以放在哪裡就無所謂了

      8) 如果 class A 獨立存在,那麼A就是一個類,如果 Object A 獨立存在,那麼A就是一個“靜態”性質的對象[即類對象],在 Object A 中聲明的屬性和方法可以通過 A.屬性和A.方法 來實現調用

      9) 當一個文件中,存在半生類和伴生對象時,文件的圖標會發生變化

  8.1.5 最佳實踐-使用伴生對象完成小孩堆雪人游戲 

      設計一個var total Int 表示總人數,我們在創建一個小孩時,就把total加1,並且total是所有對象共用的就ok了,使用伴生對象來解決

object boke_demo01 {

  def main(args: Array[String]): Unit = {
    //創建三個小孩
    val child0 = new Child("鐵蛋")
    val child1 = new Child("狗蛋")
    val child2 = new Child("熊大")
    Child.joinGame(child0)
    Child.joinGame(child1)
    Child.joinGame(child2)
    Child.showNum()
  }
}

class Child(cName: String) {
  var name = cName
}

object Child {
  //統計共有多少小孩的屬性
  var totalChildNum = 0

  def joinGame(child: Child): Unit = {
    printf("%s 小孩加入了游戲\n", child.name)
    //totalChildNum 加1
    totalChildNum += 1
  }

  def showNum(): Unit = {
    printf("當前有%d小孩玩游戲\n", totalChildNum)
  }
}

  8.1.6 伴生對象-apply方法 

      在伴生對象中定義apply方法,可以實現:類名(參數)方式來創建對象實例

object boke_demo01 {

  def main(args: Array[String]): Unit = {
    val list = List(1, 2, 5)
    println(list)

    val pig = new Pig("狗蛋")

    //使用apply方法來創建對象
    val pig2 = Pig("鐵蛋") //自動  apply(pName: String)
    val pig3 = Pig() // 自動觸發 apply()

    println("pig2.name=" + pig2.name) //小黑豬
    println("pig3.name=" + pig3.name) //匿名豬豬
  }
}

//案例演示apply方法.
class Pig(pName: String) {
  var name: String = pName
}

object Pig {
  //編寫一個apply
  def apply(pName: String): Pig = new Pig(pName)

  def apply(): Pig = new Pig("匿名")
}

8.2 單例對象 

      這個部分將在Scala設計模式專題進行介紹

8.3 介面 

  8.3.1 回顧Java介面 

      -聲明介面

        interface介面名

      -實現介面

        class 類名 implements 介面1,介面2

      -Java介面的使用小結

        1) 在Java中,一個類可以實現多個介面

        2) 在Java中,介面之間支持多繼承

        3) 介面中屬性都是常量

        4) 介面中的方法都試抽象的

  8.3.2 Scala介面的介紹 

      1) 從面向對象來看,介面並不屬於面向對象的範疇,Scala是純面向對象的語言,在Scala中,沒有介面

      2) Scala語言中,採用特質trait(特征)來代替介面的概念,也就是說,多個類具有相同的特質(特征)時,就可以將這個特質(特征)獨立出來,採用關鍵字trait聲明。理解trait等價於(interface+abstract class)

      3) Scala繼承特質(trait)的示意圖

      Scala繼承特質示意圖

  8.3.3 trait的聲明 

      trait 特質名 {

        trait 體

      }

      1) trait 命名 一般首字母大寫 Cloneable,Serializable

        object T1 extends Serializable {

        }

        Serializable:就是Scala的一個特質

      -在Scala中,Java中的介面可以當做特質使用

object boke_demo01 {

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

  }
}

//trait Serializable extends Any with java.io.Serializable
//在scala中,java的介面都可以當做trait來使用(如上面的語法)
object T1 extends Serializable {
  
}

object T2 extends Cloneable {

}

  8.3.4 Scala中trait的使用

      一個類具有某種特質(特征),就意味著這個類滿足了這個特質(特征)的所有要素,所以在使用時,也採用了extends關鍵字,如果有多個特質或存在父類,那麼需要採用with關鍵字連接

      1) 沒有父類

      class 類名 extends 特質1 with 特質2 with 特質3...

      2) 有父類

      class 類名 extends 父類 with 特質1 with 特質2 with 特質3...

8.4 特質(trait)

  8.4.1 特質的快速入門案例

      Scala引入trait特質,第一可以替代Java的介面,第二也是對單繼承機制的一種補充

      引入特質

  8.4.2 案例代碼

object boke_demo01 {

  def main(args: Array[String]): Unit = {
    val c = new C()
    val f = new F()
    c.getConnect() // 連接mysql資料庫...
    f.getConnect() // 連接oracle資料庫..
  }
}

//按照要求定義一個trait
trait Trait {
  //定義一個規範
  def getConnect()
}

//先將六個類的關係寫出
class A {}

class B extends A {}

class C extends A with Trait {
  override def getConnect(): Unit = {
    println("連接mysql資料庫...")
  }
}

class D {}

class E extends D {}

class F extends D with Trait {
  override def getConnect(): Unit = {
    println("連接oracle資料庫..")
  }
}

  8.4.3 特質trait的再說明

      1) Scala提供了特質(trait),特質可以同時擁有抽象方法和具體方法,一個類可以實現/繼承多個特質

object boke_demo01 {

  def main(args: Array[String]): Unit = {
    //創建sheep
    val sheep = new Sheep
    sheep.sayHi()
    sheep.sayHello()
  }
}

//當一個trait有抽象方法和非抽象方法時
//1. 一個trait在底層對應兩個 Trait.class 介面
//2. 還對應 Trait$class.class Trait$class抽象類
trait Trait {
  //抽象方法
  def sayHi()

  //實現普通方法
  def sayHello(): Unit = {
    println("say Hello~~")
  }
}


//當trait有介面和抽象類是
//1.class Sheep extends Trait 在底層 對應
//2.class Sheep implements  Trait
//3.當在 Sheep 類中要使用 Trait的實現的方法,就通過  Trait$class
class Sheep extends Trait {
  override def sayHi(): Unit = {
    println("小羊say hi~~")
  }
}

特質的再說明

      2) 特質中沒有實現的方法就是抽象方法。類通過extends繼承特質,通過with關鍵字可以繼承多個特質

      3) 所有的Java介面都可以當做Scala特質使用

      Java介面當做Scala的特質

 

  8.4.4帶有特質的對象,動態混入 

      1) 除了可以在類聲明時繼承特質以外,還可以在構建對象時混入特質,擴展目標類的功能

      2) 此種方法也可以應用於對抽象類功能進行擴展

      3) 動態混入是Scala特有的方式(Java沒有動態混入),可在不修改類聲明/定義的情況下,擴展類的功能,非常的靈活,耦合性低

      4) 動態混入可以在不影響原有的繼承關係的基礎上,給指定的類擴展功能

      5) 同時要註意動態混入時,如果抽象類有抽象方法,如何混入

      6) 案例演示

object boke_demo01 {

  def main(args: Array[String]): Unit = {
    //在不修改類的定義基礎,讓它們可以使用trait方法
    val oracleDB = new OracleDB with Operate
    oracleDB.insert(100) //

    val mySQL = new MySQL with Operate
    mySQL.insert(200)

    //如果一個抽象類有抽象方法,如何動態混入特質
    val mySql_ = new MySQL_ with Operate {
      override def say(): Unit = {
        println("say")
      }
    }
    mySql_.insert(999)
    mySql_.say()
  }
}

trait Operate { //特質
  def insert(id: Int): Unit = { //方法(實現)
    println("插入數據 = " + id)
  }
}

class OracleDB { //空
}

abstract class MySQL { //空
}

abstract class MySQL_ { //空
  def say()
}

      -在Scala中創建對象的4種方式

      1) new 對象

      2) apply 創建

      3) 匿名子類方式

      4) 動態混入  

  8.4.5 疊加特質 

      -基本介紹

      構建對象的同時如果混入多個特質,稱之為疊加特質,那麼特質聲明順序從左到右,方法執行順序從右到左

      -疊加特質應用案例

      目的:分析疊加特質時,對象的構建順序,和執行方法的順序

      案例演示:

object boke_demo01 {

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

    //說明
    //1. 創建 MySQL實例時,動態的混入 DB 和 File

    //研究第一個問題,當我們創建一個動態混入對象時,其順序是怎樣的
    //總結一句話
    //Scala在疊加特質的時候,會首先從後面的特質開始執行(即從左到右)
    //1.Operate...
    //2.Data
    //3.DB
    //4.File
    val mysql = new MySQL with DB with File
    println(mysql)

    //研究第2個問題,當我們執行一個動態混入對象的方法,其執行順序是怎樣的
    //順序是,(1)從右到左開始執行 , (2)當執行到super時,是指的左邊的特質 (3) 如果左邊沒有特質了,則super就是父特質
    //1. 向文件"
    //2. 向資料庫
    //3. 插入數據 100
    mysql.insert(100)

    println("===================================================")
    //練習題
    val mySQL = new MySQL with File with DB
    mySQL.insert(999)
    //構建順序
    //1.Operate...
    //2.Data
    //3.File
    //4.DB

    //執行順序
    //1. 向資料庫
    //2. 向文件
    //3. 插入數據 = 999
  }
}

trait Operate { //特點
  println("Operate...")

  def insert(id: Int) //抽象方法
}

trait Data extends Operate { //特質,繼承了Operate
  println("Data")

  override def insert(id: Int): Unit = { //實現/重寫 Operate 的insert
    println("插入數據 = " + id)
  }
}

trait DB extends Data { //特質,繼承 Data
  println("DB")

  override def insert(id: Int): Unit = { // 重寫 Data 的insert
    println("向資料庫")
    super.insert(id)
  }
}

trait File extends Data { //特質,繼承 Data
  println("File")

  override def insert(id: Int): Unit = { // 重寫 Data 的insert
    println("向文件")
    //super.insert(id) //調用了insert方法(難點),這裡super在動態混入時,不一定是父類
    //如果我們希望直接調用Data的insert方法,可以指定,如下
    //說明:super[?] ?的類型,必須是當前的特質的直接父特質(超類)
    super[Data].insert(id)
  }
}

class MySQL {} //普通類

      -疊加特質註意事項和細節

        1) 特質聲明順序從左到右

        2) Scala 在執行疊加對象的方法時,會首先從後面的特質(從右向左)開始執行

        3) Scala 中特質中如果調用 super,並不是表示調用父特質的方法,而是向前面(左邊)繼續 查找特質,如果找不到,才會去父特質查找

        4) 如果想要調用具體特質的方法,可以指定:super[特質].xxx(...).其中的泛型必須是該特質的直接超類類型

  8.4.6 當作富介面使用的特質 

      富介面:即該特質中既有抽象方法,又有非抽象方法

trait Operate {
  def insert(id: Int) //抽象
  def pageQuery(pageno: Int, pagesize: Int): Unit = { //實現
    println("分頁查詢")
  }
}

  8.4.7 特質中的具體欄位 

      特質中可以定義具體欄位,如果初始化了就是具體欄位,如果不初始化就是抽象欄位,混入該特質的類就具有了該欄位,欄位不是繼承,而是直接加入類,成為自己的欄位

object boke_demo01 {

  def main(args: Array[String]): Unit = {
    val mySQL = new MySQL with DB {
      override var sal = 10
    }
  }
}

trait DB {
  var sal: Int //抽象欄位
  var opertype: String = "insert"

  def insert(): Unit = {
  }
}

class MySQL {}

      -反編譯後的代碼

編譯後的代碼

  8.4.8 特質中的抽象欄位  

      特質中未被初始化的欄位在具體的子類中必須被重寫

  8.4.9 特質構造順序 

      -介紹

        特質也是有構造器的,構造器中的內容由“欄位的初始化”和一些其他語句構成

      -第一種特質構造順序(聲明類的同時混入特質)

        1) 調用當前類的超類構造器

        2) 第一個特質的父特質構造器

        3) 第一個特質構造器

        4) 第二個特質構造器的父特質構造器,如果已經執行過就不再執行

        5) 第二個特質構造器

        6) ......重覆4,5的步驟(如果有第3個,第4個特質)

        7) 當前類構造器

      -第二種特質構造順序(在構建對象時,動態混入特質)

        1) 調用當前類的超類構造器

        2) 當前類構造器

        3) 第一個特質構造器的父特質構造器

        4) 第一個特質構造器

        5) 第二個特質構造器的父特質構造器,如果已經執行過就不再執行

        6) 第二個特質構造器

        7) ......重覆4,5的步驟(如果有第3個,第4個特質)

        8) 當前類構造器

      -兩種方式對構造順序的影響

        1) 第一種方式實際是構建類對象,在混入特質時,該對象還沒有創建

        2) 第二種方式實際是構造匿名子類,可以理解成在混入特質時,對象已經創建了

      -案例演示

object boke_demo01 {

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

    //這時FF是這樣 形式 class FF extends EE with CC with DD
    /*
    調用當前類的超類構造器
第一個特質的父特質構造器
第一個特質構造器
第二個特質構造器的父特質構造器, 如果已經執行過,就不再執行
第二個特質構造器
.......重覆4,5的步驟(如果有第3個,第4個特質)
當前類構造器   [案例演示]

     */
    //1. E...
    //2. A...
    //3. B....
    //4. C....
    //5. D....
    //6. F....
    val ff1 = new FF()

    println(ff1)

    //這時我們是動態混入
    /*
    先創建 new KK 對象,然後再混入其它特質

    調用當前類的超類構造器
當前類構造器
第一個特質構造器的父特質構造器
第一個特質構造器.
第二個特質構造器的父特質構造器, 如果已經執行過,就不再執行
第二個特質構造器
.......重覆5,6的步驟(如果有第3個,第4個特質)
當前類構造器   [案例演示]

     */
    //1. E...
    //2. K....
    //3. A...
    //4. B
    //5. C
    //6. D
    println("=======================")
    val ff2 = new KK with CC with DD
    println(ff2)

  }
}

trait AA {
  println("A...")
}

trait BB extends AA {
  println("B....")
}

trait CC extends BB {
  println("C....")
}

trait DD extends BB {
  println("D....")
}

class EE { //普通類
  println("E...")
}

class FF extends EE with CC with DD { //先繼承了EE類,然後再繼承CC 和DD
  println("F....")
}

class KK extends EE { //KK直接繼承了普通類EE
  println("K....")
}

  8.4.10 擴展類的特質 

      -特質可以繼承類,以用來拓展該特質的一些功能

trait LoggedException extends Exception {
  def log(): Unit = {
    println(getMessage()) // 方法來自於Exception類
  }
}

      -所有混入該特質的類,會自動成為那個特質所繼承的超類的子類

//1. LoggedException 繼承了 Exception
//2. LoggedException 特質就可以  Exception 功能
trait LoggedException extends Exception {
  def log(): Unit = {
    println(getMessage()) // 方法來自於Exception類
  }
}

      -如果混入該特質的類,已經繼承了另一個類(A類),則要求A類是特質超類的子類,否則就會出現了多繼承現象,發生錯誤

object boke_demo01 {

  def main(args: Array[String]): Unit = {
    println("h~~")
  }
}

//說明
//1. LoggedException 繼承了 Exception
//2. LoggedException 特質就可以  Exception 功能
trait LoggedException extends Exception {
  def log(): Unit = {
    println(getMessage()) // 方法來自於Exception類
  }
}

//因為 UnhappyException 繼承了 LoggedException
//而 LoggedException 繼承了  Exception
//UnhappyException 就成為 Exception子類
class UnhappyException extends LoggedException {
  // 已經是Exception的子類了,所以可以重寫方法
  override def getMessage = "錯誤消息!"
}

// 如果混入該特質的類,已經繼承了另一個類(A類),則要求A類是特質超類的子類,
// 否則就會出現了多繼承現象,發生錯誤。
class UnhappyException2 extends IndexOutOfBoundsException with LoggedException {
  // 已經是Exception的子類了,所以可以重寫方法
  override def getMessage = "錯誤消息!"
}

class CCC {}

//錯誤的原因是 CCC 不是 Exception子類
//class UnhappyException3 extends CCC with LoggedException{
//  // 已經是Exception的子類了,所以可以重寫方法
//  override def getMessage = "錯誤消息!"
//}

  8.4.11 自身類型 

      -說明

        自身類型:主要是為瞭解決特質的迴圈依賴問題,同時可以確保特質在不擴展某個類的情況下,依然可以做到限制混入該特質的類的類型

      -應用案例

        舉例說明自身類型特質,以及如何使用自身類型特質

object boke_demo01 {

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

  }
}

//Logger就是自身類型特質,當這裡做了自身類型後,那麼
// trait Logger extends Exception,要求混入該特質的類也是 Exception子類
trait Logger {
  // 明確告訴編譯器,我就是Exception,如果沒有這句話,下麵的getMessage不能調用
  this: Exception =>
  def log(): Unit = {
    // 既然我就是Exception, 那麼就可以調用其中的方法
    println(getMessage)
  }
}

//class Console extends  Logger {} //對嗎? 錯誤
//class Console extends Exception with Logger {}//對嗎? 正確

8.5 嵌套類

  8.5.1 嵌套類的使用1 

  

  8.5.2 Scala嵌套類的使用2

      編寫程式,在內部類中訪問外部類的屬性

      -方式1

        內部類如果想要訪問外部類的屬性,可以通過外部類對象訪問

        即訪問形式:外部類名.this.屬性名

        案例演示

//外部類
//內部類訪問外部類的屬性的方法1 外部類名.this.屬性
class ScalaOuterClass {
  //定義兩個屬性
  var name = "Jack"
  private var sal = 199.6

  class ScalaInnerClass { //成員內部類,

    def info() = {
      // 訪問方式:外部類名.this.屬性名
      // 怎麼理解 ScalaOuterClass.this 就相當於是 ScalaOuterClass 這個外部類的一個實例,
      // 然後通過 ScalaOuterClass.this 實例對象去訪問 name 屬性
      // 只是這種寫法比較特別,學習java的同學可能更容易理解 ScalaOuterClass.class 的寫法.
      println("name = " + ScalaOuterClass.this.name
        + " sal =" + ScalaOuterClass.this.sal)
    }
  }

}

      -方式2

        內部類如果想要訪問外部類的屬性,也可以通過外部類別名訪問(推薦)

        即訪問方式:外部類名別名.屬性名

        案例演示

object boke_demo01 {

  def main(args: Array[String]): Unit = {
    //測試1. 創建了兩個外部類的實例
    val outer1: ScalaOuterClass = new ScalaOuterClass();
    val outer2: ScalaOuterClass = new ScalaOuterClass();

    //在scala中,創建成員內部類的語法是
    //對象.內部類  的方式創建, 這裡語法可以看出在scala中,預設情況下內部類實例和外部對象關聯
    val inner1 = new outer1.ScalaInnerClass
    val inner2 = new outer2.ScalaInnerClass

    //測試一下使用inner1 去調用 info()
    inner1.info()

    //這裡我們去調用test
    inner1.test(inner1)
    //在預設情況下,scala的內部類的實例和創建該內部類實例的外部對象關聯.
    //
    inner1.test(inner2)
    inner2.test(inner2)


    //創建靜態內部類實例
    val staticInner = new ScalaOuterClass.ScalaStaticInnerClass()


  }
}


//外部類
//內部類訪問外部類的屬性的方法2 使用別名的方式
//1. 將外部類屬性,寫在別名後面
class ScalaOuterClass {
  myouter => //這裡我們可以這裡理解 外部類的別名 看做是外部類的一個實例
  class ScalaInnerClass { //成員內部類,

    def info() = {
      // 訪問方式:外部類別名.屬性名
      // 只是這種寫法比較特別,學習java的同學可能更容易理解 ScalaOuterClass.class 的寫法.
      println("name~ = " + myouter.name
        + " sal~ =" + myouter.sal)
    }
  }

  //定義兩個屬性
  var name = "Jack"
  private var sal = 999.9
}


object ScalaOuterClass { //伴生對象
class ScalaStaticInnerClass { //靜態內部類
}

}

  8.5.3 類型投影  

      -案例演示

//外部類
//內部類訪問外部類的屬性的方法2 使用別名的方式
//1. 將外部類屬性,寫在別名後面
class ScalaOuterClass {
  myouter => //這裡我們可以這裡理解 外部類的別名 看做是外部類的一個實例
  class ScalaInnerClass { //成員內部類,

    def info() = {
      // 訪問方式:外部類別名.屬性名
      // 只是這種寫法比較特別,學習java的同學可能更容易理解 ScalaOuterClass.class 的寫法.
      println("name~ = " + myouter.name
        + " sal~ =" + myouter.sal)
    }

    //這裡有一個方法,可以接受ScalaInnerClass實例
    //下麵的 ScalaOuterClass#ScalaInnerClass 類型投影的作用就是屏蔽 外部對象對內部類對象的
    //影響
    def test(ic: ScalaOuterClass#ScalaInnerClass): Unit = {
      System.out.println("使用了類型投影" + ic)
    }

  }

  //定義兩個屬性
  var name = "Jack"
  private var sal = 999.9
}

      -解決方式-類型投影 

        類型投影是指:在方法聲明上,如果使用 外部類#內部類 的方式,表示忽略內部類的對象關係,等同於Java中內部類的語法操作,我們將這種方法稱之為 類型投影(即:忽略對象的創建方式,只考慮類型)

 


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

-Advertisement-
Play Games
更多相關文章
  • 新聞 "FableConf 2019開始徵集提案" "2019理事會選舉 " "如同DSL一般的Elmish封裝器fable elmish,可以創建控制台或者終端界面" "介紹VS Code的遠程開發" "F (.NET Core 2.1)開發容器" "SAFE開發容器定義示例" "Rider 20 ...
  • #include<iostream> #include<string> #define ml 10 using namespace std; typedef struct{//定義Data數據項 std::string name; long num; }Data; struct Link{//定義結 ...
  • 數組,是我們最常用的,但是有時候,我們要用數組,但是又不知道數組的類的長度的時候, 我們java就有一個很好用的工具Collection,這都是java的爸爸的用心良苦,Collection中包含List和Set 和Map,但是今天老師講了List和Set。List是有序泛型數組。Set是無序泛型數 ...
  • wc命令含義 wc命令用查看文件的行數、單詞數、字元數等信息 wc命令格式 wc [-clmw] [file ...] wc命令參數以及實例介紹 (1)最基礎的查看文件的行數、單詞數、字元數等信息 (2)-l 選項 :統計文件的行數信息 (3) -w 選項:統計文件的單詞數信息 (4)-c 選項:統 ...
  • 1 import pandas as pd 2 import numpy as np 3 4 # merge合併 ,類似於Excel中的vlookup 5 6 df1 = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'], 7 'A': ['A0', 'A1... ...
  • 一,複習 二,今日內容 三,模塊 四,導入模板完成的三件事 五,起別名 六,模塊的分類 七,模塊的載入順序 八,環境變數 九,from...import語法導入 十,from...import * 十一,鏈式導入 十二,迴圈導入 ...
  • 圖的概念、存儲及遍歷 圖是一種特殊的數據結構,由點和邊構成,它可以用來描述元素之間的網狀關係,這個網狀沒有順序,也沒有層次,就是簡單的把各個元素連接起來。圖在我們的生活中也十分常見,地圖就是最簡單的例子。 圖的基本概念: 頂點集合為V,邊集合為E的圖記作G=(V,E)。另外,G=(V,E)的頂點數和 ...
  • 第四章 文件操作 4.1 文件基本操作 4.2 打開模式 r / w / a 【只讀只寫字元串】 r+ / w+ / a+ 【可讀可寫字元串】 rb / wb / ab 【只讀只寫二進位】 r+b / w+b / a+b 【可讀可寫二進位】 4.3 操作 read() , 全部讀到記憶體 read(1 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...