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
更多相關文章
  • Pattern模式是Dart 3.0發佈的3個高級特性之一,在第09天我們學習了模式的概覽和用法,對模式的強大之處有了基本的認識,今天我們來看看Dart中的全部模式類型,總共有15種,它們包括邏輯或、邏輯與、關係、值轉換、空檢測、空斷言、常量、變數、標識符、括弧、List列表、Map映射、Recor... ...
  • 簡介 SSE 的全稱是 Server Sent Events,即伺服器推送事件。它是一種基於 HTTP 的伺服器到客戶端的單向(半雙工)通信機制,使伺服器能夠主動將實時數據推送給客戶端,而不需要客戶端多次發起請求。 官方文檔:https://developer.mozilla.org/en-US/d ...
  • 跨域問題是指在瀏覽器上運行的Web應用程式試圖通過XMLHttpRequest或Fetch API等方式向不同源(功能變數名稱、協議或埠)的伺服器發送請求時,瀏覽器會根據同源策略(Same-Origin Policy)阻止這種行為。同源策略是一種安全機制,用於限制來自不同源的頁面對當前頁面的訪問。它可以防... ...
  • 信息學 學習/複習 抽簽器(附源碼) 效果圖 以下是源代碼,可自行修改 [C++] //By DijkstraPhoenix #include<bits/stdc++.h> #include<windows.h> using namespace std; vector<string>item; in ...
  • 萬里歸來年愈少 PB編程新思維10.5:外傳2(PowerPlume下一代解決方案) 前言 今天我們就來盤點一下,PB下一代開發的所有技術可能性。所謂下一代開發技術,就是指脫離或半脫離PBVM的應用開發技術,主要指後端。 後端技術彙總 前端PB+JSON 前端PB+BLOB WEB 後端PBVM P ...
  • 我們繼續延申調試事件的話題,實現進程轉存功能,進程轉儲功能是指通過調試API使獲得了目標進程式控制制權的進程,將目標進程的記憶體中的數據完整地轉存到本地磁碟上,對於加殼軟體,通常會通過加密、壓縮等手段來保護其代碼和數據,使其不易被分析。在這種情況下,通過進程轉儲功能,可以將加殼程式的記憶體鏡像完整地保存到本... ...
  • 一、@Valid 註解的作用 @Valid 註解是 javax.validation 包中的一個註解,它可以用來標註需要驗證的數據對象。當一個帶有 @Valid 註解的對象傳遞給 SpringMVC 的控制器方法時,SpringMVC 會自動調用驗證器來驗證這個對象。 二、數據驗證的流程 Sprin ...
  • 在當今互聯網時代,移動應用和網頁應用的發展極大地推動了前後端分離開發模式的興起。傳統的後端渲染方式已經不能滿足用戶對高性能和優質用戶體驗的需求,於是前後端分離逐漸成為了一種主流的開發模式。前後端分離開發模式通過將前端和後端的開發分離,極大地提高了開發效率和團隊協作。前端開發人員專註於用戶界面和交互邏... ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...