Flutter/Dart第09天:Dart高級特殊Pattern模式的概覽和用法

来源:https://www.cnblogs.com/obullxl/archive/2023/10/04/NTopic2023100401.html
-Advertisement-
Play Games

Dart 3.0在語法層面共發佈了3個高級特性,第一個特性Record記錄我們在前面已經學習和探究。今天我們來學習第二個高級類型Pattern模式,由於內容較多,共分2篇文章進行介紹,本文首先介紹模式的概覽和用法,包括匹配、解構、在變數申明、賦值、迴圈、表達式等應用場景…… ...


Dart官方文檔:https://dart.dev/language/patterns

重要說明:本博客基於Dart官網文檔,但並不是簡單的對官網進行翻譯,在覆蓋核心功能情況下,我會根據個人研發經驗,加入自己的一些擴展問題和場景驗證。

Pattern模式匹配的定義

官網定義:Patterns are a syntactic category in the Dart language, like statements and expressions. A pattern represents the shape of a set of values that it may match against actual values.

初看定義不太好理解,感覺有點繞,大概意思:模式是Dart語言的一種語法分類,就像聲明和表達式一樣。模式代表了一組實際值的形狀,這個形狀可以匹配到實際值。(特別註意:這裡的Pattern和正則表達式沒有任何關係!)

有幾個重要的概念:語法、形狀、匹配

  1. 語法:語法是一個編碼語言的基礎,可見模式在Dart中的重要程度。
  2. 形狀:或者說結構,就是一組實際值是如何組織在一起的一種抽象(結構定義)。
  3. 匹配:根據一組值的形狀,我們匹配到對應的值。

舉一個List列表的例子,可能不是完全恰當,但是可以幫忙我們理解模式的這段定義:

  1. 語法:final aList = [1, 2, 3];這個是定義列表的語句,其中aList代表變數名,列表採用[]包裹,元素採用,分隔,最後;結束等等,這些都是Dart中的語法。
  2. 形狀:列表採用[]包裹,元素採用,分隔,元素類型int由Dart自動推導出來,這些都是這一組值的形狀,就是長什麼樣。
  3. 匹配:aList[0] == 1根據列表的語法和形狀,可以匹配到實際值。

Pattern模式的用途

Pattern模式主要作用:匹配值、解構值。匹配和解構可以同時作用,需要根據上下文和值的形狀或結構具體來看。

首先,模式可以讓我們確定某個值的一些信息,包括:

  1. 有一個明確的形狀(或者結構)。
  2. 是一個明確的常量。
  3. 它和某個值相等(即可用於比較)。
  4. 有一個明確的類型。

然後,模式解構可以用一種便利的語法,把這個值進行分解,還可以綁定到某個變數上面。

匹配

匹配就是校驗某個值是否符合我們預期,換句話說,我們是在檢測某個值是否符合某種結構且它的值與指定值相等。

我們在編碼過程中,很多邏輯其實都是在進行模式,舉例如下:

// 常數匹配:1 == number ?
switch (number) {
  case 1:
    print('one');
}

// 列表匹配:`obj`是一個2個元素列表
// 元素匹配:`obj`的2個元素值分別為`a`和`b`
const a = 'a';
const b = 'b';
switch (obj) {
  case [a, b]:
    print('$a, $b');
}

解構

當一個對象和一個模式相匹配,那麼這個模式可以訪問對象的數據,並可以把這個對象拆分成不同部分。換句話說,這個模式解構了這個對象。

代碼樣例:如下代碼,List列表解構,和解構模式中的嵌套匹配模式。

// 列表解構:`[a, b, c]`結構`numList`對象
// 1. 匹配:`[a, b, c]`代表了具有3個元素的列表
// 2. 拆分:列表的3個元素,分別賦值給了新的變數`a`、`b`和`cs`
var numList = [1, 2, 3];
var [a, b, c] = numList;
print(a + b + c);

// 列表模式:包含2個元素,且第1個元素是`a`或`b`,第2個元素賦值給變數`c`
switch (list) {
  case ['a' || 'b', var c]:
    print(c);
}

模式的應用場景

在Dart語言總,有幾個常見可以使用模式:

  1. 局部變數的申明賦值
  2. forfor-in迴圈語句。
  3. if-caseswitch-case語句。
  4. 集合相關的控制流

變數申明

我們可以在Dart允許本地變數聲明的任何地方使用模式變數聲明,模式變數申明必須由var或者final + 模式組成(這也是Dart的模式變數的語法)。

代碼樣例:如下代碼,使用模式,我們申明瞭abc三個變數(並且完成賦值)。

var (a, [b, c]) = ('str', [1, 2]);

變數賦值

上小節變數申明的代碼樣例中,其實已經進行了模式變數賦值:首先進行模式匹配,然後解構對象,最終進行遍歷賦值。

代碼樣例:如下代碼,採用變數賦值模式,輕鬆進行了2個元素值交換,而無需使用第3個變數。

var (a, b) = ('left', 'right');
(b, a) = (a, b);
print('$a $b');

Switch和表達式模式

本文開頭的樣例其實已經提到,任何case的語句其實都包含了一個模式。在case中,可以應用任何的模式,變數賦值的作用域僅在Case語句內部。

Case模式可以匹配失敗,它允許控制流:

  1. 匹配並解構switch對象。
  2. 匹配失敗,則繼續執行匹配。
switch (obj) {
  // 匹配:1 == obj
  case 1:
    print('one');

  // 匹配:[first, last]區間
  case >= first && <= last:
    print('in range');

  // 匹配:Record記錄,包含2個欄位
  // 賦值:`a`和`b`局部變數(作用域:本Case內部)
  case (var a, var b):
    print('a = $a, b = $b');

  default:
}

// 邏輯或模式:多個case共用
var isPrimary = switch (color) {
  Color.red || Color.yellow || Color.blue => true,
  _ => false
};

switch (shape) {
  case Square(size: var s) || Circle(size: var s) when s > 0:
    print('Non-empty symmetric shape');
}

for和for-in迴圈模式

主要作用:迭代和解構集合。

代碼樣例:如下代碼,for迴圈匹配模式,並解構和賦值給變數。

Map<String, int> hist = {
  'a': 23,
  'b': 100,
};

// 匹配:`MapEntry`類型,繼續匹配`key`和`value`命名欄位子模式
// 賦值:調用`key`和`value`的`getter`並賦值給`key`和`value`變數
for (var MapEntry(key: key, value: count) in hist.entries) {
  print('$key occurred $count times');
}

// 上訴代碼的簡寫
for (var MapEntry(:key, value: count) in hist.entries) {
  print('$key occurred $count times');
}

其他場景模式

本文前面的章節,我們主要是展示Dart類型模式和解構,當然也包括(a, b)內容交換的例子。本章進一步學習其他的場景模式。

通過本章學習,主要解決我們幾個問題:

  1. 什麼時候我們需要用到模式,我們為什麼需要模式?
  2. 模式主要解決什麼類型的問題?
  3. 什麼樣的模式最適合?

解構多個返回值

在之前的學習中,Record記錄的用途之一就是聚合多個值,並讓函數返回多個值。模式能匹配並解構Record記錄,並賦值給局部變數。

代碼樣例:如下代碼,userInfo(json)返回一個位置欄位的記錄,被解構並把位置值賦值給了nameage局部變數。

// Record記錄的使用
var info = userInfo(json);
var name = info.$1;
var age = info.$2;

// Record解構和賦值
var (name, age) = userInfo(json);

解構類實例

對象模式能匹配命名的對象類型,可以解構對象的數據,並調用對象屬性的getters方法進行賦值。

代碼樣例:如下代碼,命名類型Foo實例myFoo被解構併進行賦值給onetwo變數。

final Foo myFoo = Foo(one: 'one', two: 2);
var Foo(:one, :two) = myFoo;
print('one $one, two $two');

代數數據類型

對象解構和Switch模式有助於編寫代數數據類型風格代碼,它比較適合以下幾種場景:

  1. 有一群相關聯的類型。
  2. 每個類型都有一個相同的操作,但這個操作對每個類型而言又有差異。
  3. 我們希望把這個操作能一把實現,而不是把實現散落在每個類型中。

樣例代碼:如下代碼,Shape是一個父類,2個或更多的子類都有計算面積的方法,最終通過calculateArea()函數一把實現了。

sealed class Shape {}

class Square implements Shape {
  final double length;
  Square(this.length);
}

class Circle implements Shape {
  final double radius;
  Circle(this.radius);
}

double calculateArea(Shape shape) => switch (shape) {
      Square(length: var l) => l * l,
      Circle(radius: var r) => math.pi * r * r
    };

校驗JSON格式

前面章節,我們學習了ListMap類型的匹配和解構,它們也適用於JSON的key-value鍵值對。

代碼樣例:如下代碼,在已知JSON格式的情況下,我們可以通過List和Map完成JSON的解構和賦值。

var json = {
  'user': ['Lily', 13]
};

var {'user': [name, age]} = json;

但是,當JSON格式不明確的情況下,我們可以通過解構來校驗JSON的格式。

代碼樣例:如下代碼,我們通過case模式,完成了JSON數據的校驗和賦值。

if (json case {'user': [String name, int age]}) {
  print('User $name is $age years old.');
}

如上代碼,Case模式的匹配和賦值操作如下:

  1. json是一個非空的map,進一步匹配map模式
  2. json包含一個名為user的屬性,且它是一個包含2個元素的list類型,list中2個元素類型分別為Stringint
  3. 最終,list的2個元素分別賦值給了nameage局部變數。

我的本博客原地址:https://ntopic.cn/p/2023100401


本文作者:奔跑的蝸牛,轉載請註明原文鏈接:https://ntopic.cn


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

-Advertisement-
Play Games
更多相關文章
  • 目錄: 1.前言 2.設計與分析 3.BUG與修正 4.缺陷與改進 5.總結 一、前言 題目集1的題目都是比較基礎的題,不需要用到其他的類,而且所有的題代碼行數都不超過40行。知識點集中在分支選擇和浮點數的處理上,題量適中,難度也較小。比較適合初學Java的學生來熟悉java,瞭解java與之前所學 ...
  • 隨著移動互聯網的發展,手機號碼已經成為我們日常生活中不可或缺的一部分。然而,在我們使用手機號碼時,我們經常需要瞭解某個手機號碼的歸屬地,以便更好的進行溝通和交流。那麼如何快速定位手機號碼的歸屬地呢?本文將基於數據源下載,用代碼的方式來實現這一目標。 一、數據源下載 在實現手機號碼定位功能之前,我們需 ...
  • 示例,將新列表中的所有值設置為 'hello': newlist = ['hello' for x in fruits] 表達式還可以包含條件,不像篩選器那樣,而是作為操縱結果的一種方式: 示例,返回 "orange" 而不是 "banana": newlist = [x if x != "bana ...
  • 【中秋國慶不斷更】OpenHarmony組件內狀態變數使用:@State裝飾器 @State裝飾的變數,或稱為狀態變數,一旦變數擁有了狀態屬性,就和自定義組件的渲染綁定起來。當狀態改變時,UI會發生對應的渲染改變。 在狀態變數相關裝飾器中,@State是最基礎的,使變數擁有狀態屬性的裝飾器,它也是大 ...
  • 【中秋國慶不斷更】HarmonyOS對通知類消息的管理與發佈通知(下) 一、發佈進度條類型通知 進度條通知也是常見的通知類型,主要應用於文件下載、事務處理進度顯示。HarmonyOS提供了進度條模板,發佈通知應用設置好進度條模板的屬性值,如模板名、模板數據,通過通知子系統發送到通知欄顯示。 目前系統 ...
  • Python中的變數 變數的定義 程式中,數據都臨時存儲在記憶體中。每一個被存儲在記憶體的數據都有一個記憶體地址。其中特定的數據被我們所使用,因此我們為那些記憶體地址定義了名稱。這一名稱被稱作 標識符,又稱變數名。而與變數名對應記憶體地址中的數據被稱為變數值。 總結:變數為記憶體中特定的數據。它的記憶體地址的名稱 ...
  • 在這,您將學習瞭解 Spring Boot Starter Parent, 它是 Spring Boot 提供的父級 Pom 文件,旨在提供自動版本依賴管理,幫助我們輕鬆快速地進行 Spring Boot 開發。 什麼是 Spring Boot Starter Parent ? 通過 Spring ...
  • 用Rust手把手編寫一個wmproxy(代理,內網穿透等), HTTP及TCP內網穿透原理及運行篇 項目 ++wmproxy++ gite: https://gitee.com/tickbh/wmproxy github: https://github.com/tickbh/wmproxy 內網、公 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...