ArkTS語言入門之接口、泛型、空安全、特殊運算符等

前言

臭寶們,今天我們來學習ArkTS中最后的一些內容。

實現接口

包含implements子句的類必須實現列出的接口中定義的所有方法,但使用默認實現定義的方法除外。

interface DateInterface {now(): string;
}
class MyDate implements DateInterface {now(): string {// 在此實現return 'now';}
}

接口屬性

接口屬性可以是字段、getter、setter或getter和setter組合的形式。

interface Style {color: string;
}

接口繼承

接口可以繼承其他接口,如下面的示例所示:

interface Style {color: string;
}interface ExtendedStyle extends Style {width: number;
}

注意:繼承接口包含被繼承接口的所有屬性和方法,還可以添加自己的屬性和方法。

抽象類和接口

在上一節中,我們介紹了如何在ArkTS中使用抽象類。抽象類與接口都無法實例化。抽象類是類的抽象,抽象類用來捕捉子類的通用特性,接口是行為的抽象。在ArkTS中抽象類與接口的區別如下:

  • 一個類只能繼承一個抽象類,而一個類可以實現一個或多個接口;
  • 接口中不能含有靜態代碼塊以及靜態方法,而抽象類可以有靜態代碼塊和靜態方法;
  • 抽象類里面可以有方法的實現,但是接口完全都是抽象的,不存在方法的實現;
  • 抽象類可以有構造函數,而接口不能有構造函數。

泛型在接口和類中的應用

class CustomStack<Element> {public push(e: Element):void {// ...}
}

要使用類型CustomStack,必須為每個類型參數指定類型實參:

let s = new CustomStack<string>();
s.push('hello');

編譯器在使用泛型類型和函數時會確保類型安全。參見以下示例:

let s = new CustomStack<string>();
s.push(55); // 將會產生編譯時錯誤

泛型約束

泛型類型的類型參數可以被限制只能取某些特定的值。例如,MyHashMap<Key, Value>這個類中的Key類型參數必須具有hash方法。

interface Hashable {hash(): number;
}
class MyHashMap<Key extends Hashable, Value> {public set(k: Key, v: Value) {let h = k.hash();// ...其他代碼...}
}

在上面的例子中,Key類型擴展了Hashable,Hashable接口的所有方法都可以為key調用。

泛型函數

function last(x: number[]): number {return x[x.length - 1];
}
last([1, 2, 3]); // 3

如果需要為任何數組定義相同的函數,使用類型參數將該函數定義為泛型:

function last<T>(x: T[]): T {return x[x.length - 1];
}

現在,該函數可以與任何數組一起使用。

在函數調用中,類型實參可以顯式或隱式設置:

// 顯式設置的類型實參
last<string>(['aa', 'bb']);
last<number>([1, 2, 3]);// 隱式設置的類型實參
// 編譯器根據調用參數的類型來確定類型實參
last([1, 2, 3]);
last(['aa', 'bb']);

泛型默認值

泛型類型的類型參數可以設置默認值。這樣可以不指定實際的類型實參,而只使用泛型類型名稱。下面的示例展示了類和函數的這一點。

class SomeType {}
interface Interface <T1 = SomeType> { }
class Base <T2 = SomeType> { }
class Derived1 extends Base implements Interface { }
// Derived1在語義上等價于Derived2
class Derived2 extends Base<SomeType> implements Interface<SomeType> { }function foo<T = number>(): T {// ...
}
foo();
// 此函數在語義上等價于下面的調用
foo<number>();

空安全

在ArkTS中,ArkTS中的所有類型都是不可為空的,在下面的示例中,所有行都會導致編譯時錯誤:

let x: number = null;    // 編譯時錯誤
let y: string = null;    // 編譯時錯誤
let z: number[] = null;  // 編譯時錯誤

可以為空值的變量定義為聯合類型T | null。

let x: number | null = null;
x = 1;    // ok
x = null; // ok
if (x != null) { /* do something */ }

非空斷言運算符(!)

后綴運算符!可用于斷言其操作數為非空。

應用于可空類型的值時,它的編譯時類型變為非空類型。例如,類型將從T | null更改為T:

class A {value: number = 0;
}function foo(a: A | null) {a.value;   // 編譯時錯誤:無法訪問可空值的屬性a!.value;  // 編譯通過,如果運行時a的值非空,可以訪問到a的屬性;如果運行時a的值為空,則發生運行時異常
}

空值合并運算符(??)

空值合并二元運算符??用于檢查左側表達式的求值是否等于null或者undefined。如果是,則表達式的結果為右側表達式;否則,結果為左側表達式。

換句話說,a ?? b等價于三元運算符(a != null && a != undefined) ? a : b。

在以下示例中,getNick方法如果設置了昵稱,則返回昵稱;否則,返回空字符串:

class Person {// ...nick: string | null = null;getNick(): string {return this.nick ?? '';}
}

可選鏈

在訪問對象屬性時,如果該屬性是undefined或者null,可選鏈運算符會返回undefined。

class Person {nick: string | null = null;spouse?: PersonsetSpouse(spouse: Person): void {this.spouse = spouse;}getSpouseNick(): string | null | undefined {return this.spouse?.nick;}constructor(nick: string) {this.nick = nick;this.spouse = undefined;}
}

模塊

程序可劃分為多組編譯單元或模塊。

每個模塊都有其自己的作用域,即,在模塊中創建的任何聲明(變量、函數、類等)在該模塊之外都不可見,除非它們被顯式導出。

與此相對,從另一個模塊導出的變量、函數、類、接口等必須首先導入到模塊中。

導出

可以使用關鍵字export導出頂層的聲明。

未導出的聲明名稱被視為私有名稱,只能在聲明該名稱的模塊中使用。

export class Point {x: number = 0;y: number = 0;constructor(x: number, y: number) {this.x = x;this.y = y;}
}
export let Origin = new Point(0, 0);
export function Distance(p1: Point, p2: Point): number {return Math.sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y));
}

導入

導入聲明用于導入從其他模塊導出的實體,并在當前模塊中提供其綁定。導入聲明由兩部分組成:

  • 導入路徑,用于指定導入的模塊;
  • 導入綁定,用于定義導入的模塊中的可用實體集和使用形式(限定或不限定使用)。

假設模塊具有路徑“./utils”和導出實體“X”和“Y”。

導入綁定* as A表示綁定名稱“A”,通過A.name可訪問從導入路徑指定的模塊導出的所有實體:導入綁定可以有幾種形式。

import * as Utils from './utils';
Utils.X // 表示來自Utils的X
Utils.Y // 表示來自Utils的Y

導入綁定{ ident1, …, identN }表示將導出的實體與指定名稱綁定,該名稱可以用作簡單名稱:

import { X, Y } from './utils';
X // 表示來自utils的X
Y // 表示來自utils的Y

如果標識符列表定義了ident as alias,則實體ident將綁定在名稱alias下:

import { X as Z, Y } from './utils';
Z // 表示來自Utils的X
Y // 表示來自Utils的Y
X // 編譯時錯誤:'X'不可見

動態導入

應用開發的有些場景中,如果希望根據條件導入模塊或者按需導入模塊,可以使用動態導入代替靜態導入。

import()語法通常稱為動態導入(dynamic import),是一種類似函數的表達式,用來動態導入模塊。以這種方式調用,將返回一個promise。

如下例所示,import(modulePath)可以加載模塊并返回一個promise,該promise resolve為一個包含其所有導出的模塊對象。該表達式可以在代碼中的任意位置調用。

// Calc.ts
export function add(a:number, b:number):number {let c = a + b;console.info('Dynamic import, %d + %d = %d', a, b, c);return c;
}// Index.ts
import("./Calc").then((obj: ESObject) => {console.info(obj.add(3, 5));  
}).catch((err: Error) => {console.error("Module dynamic import error: ", err);
});

如果在異步函數中,可以使用let module = await import(modulePath)。

// say.ts
export function hi() {console.log('Hello');
}
export function bye() {console.log('Bye');
}
async function test() {let ns = await import('./say');let hi = ns.hi;let bye = ns.bye;hi();bye();
}

this 關鍵字

關鍵字this只能在類的實例方法中使用。

class A {count: string = 'a';m(i: string): void {this.count = i;}
}

使用限制:

  • 不支持this類型
  • 不支持在函數和類的靜態方法中使用this
class A {n: number = 0;f1(arg1: this) {} // 編譯時錯誤,不支持this類型static f2(arg1: number) {this.n = arg1;  // 編譯時錯誤,不支持在類的靜態方法中使用this}
}function foo(arg1: number) {this.n = i;       // 編譯時錯誤,不支持在函數中使用this
}

關鍵字this的指向:

  • 調用實例方法的對象
  • 正在構造的對象

結尾

至此,我們已經學習了ArkTS的基礎語法。下一步,我們將學習ArkUI框架。臭寶們,沖鴨!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/75273.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/75273.shtml
英文地址,請注明出處:http://en.pswp.cn/web/75273.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Maven超級詳細安裝部署

1.到底什么是Maven&#xff1f;搞清楚這個 Maven 是一個項目管理工具&#xff0c;主要用于 Java 項目的構建、依賴管理和文檔生成。 它基于項目對象模型&#xff08;POM&#xff09;&#xff0c;通過 pom.xml 文件定義項目的配置。 &#xff08;簡單說破&#xff1a;就是工程…

高并發內存池(三):PageCache(頁緩存)的實現

前言&#xff1a; 在前兩期內容中&#xff0c;我們深入探討了內存管理機制中在 ThreadCache 和 CentralCache兩個層級進行內存申請的具體實現。這兩層緩存作為高效的內存分配策略&#xff0c;能夠快速響應線程的內存需求&#xff0c;減少鎖競爭&#xff0c;提升程序性能。 本期…

機器學習 | 強化學習方法分類匯總 | 概念向

文章目錄 ??Model-Free RL vs Model-Based RL??核心定義??核心區別??Policy-Based RL vs Value-Based RL??核心定義?? 核心區別??Monte-Carlo update vs Temporal-Difference update??核心定義??核心區別??On-Policy vs Off-Policy??核心定義??核心區別…

GSO-YOLO:基于全局穩定性優化的建筑工地目標檢測算法解析

論文地址:https://arxiv.org/pdf/2407.00906 1. 論文概述 《GSO-YOLO: Global Stability Optimization YOLO for Construction Site Detection》提出了一種針對建筑工地復雜場景優化的目標檢測模型。通過融合全局優化模塊(GOM)?、穩定捕捉模塊(SCM)?和創新的AIoU損失函…

Java學習手冊:JVM、JRE和JDK的關系

在Java生態系統中&#xff0c;JVM&#xff08;Java虛擬機&#xff09;、JRE&#xff08;Java運行時環境&#xff09;和JDK&#xff08;Java開發工具包&#xff09;是三個核心概念。它們共同構成了Java語言運行和開發的基礎。理解它們之間的關系對于Java開發者來說至關重要。本文…

lanqiaoOJ 2489 進制

//x的初始值一定要設置為0,否則測試的答案是對的,但是通不過去 #include<bits/stdc.h> using namespace std; const int N50; int a[N]; using lllong long; int main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); string s"2021ABCD"; for(int i…

Python基礎知識點(類和對象)

""" 編程思維---解決問題的方式方法 面向過程---C語言 面向對象---C java python python中封裝類的語法 class 類名&#xff08;父類&#xff09; 類體 注意&#xff1a; 1.類名--約定 大駝峰法 首字母要大寫 2.父類如果有的話就寫&#xff0c;沒有的話…

記錄一下學習docker的命令(不斷補充中)

#2025-04-10,22:12############### 在wsl2中安裝了ubuntu24.04.1后有部署了docker&#xff0c; 如果沒有啟動docker可以通過下列命令啟動docker&#xff1a; sudo systemctl start docker 執行下列命令可以看到docker狀態&#xff0c;并不占用控制臺的命令&#xff1a; su…

【01BFS】# P4667 [BalticOI 2011] Switch the Lamp On 電路維修 (Day1)|普及+

本文涉及知識點 CBFS算法 題目描述 Casper is designing an electronic circuit on a N M N \times M NM rectangular grid plate. There are N M N \times M NM square tiles that are aligned to the grid on the plate. Two (out of four) opposite corners of each …

參考平面跨分割情況下的信號回流

前言&#xff1a;弄清楚信號的回流路徑&#xff0c;是學習EMC和高速的第一步&#xff01; 如果我們不管信號的回流路徑&#xff0c;會造成什么后果&#xff1f;1、信號完整性問題&#xff0c;信號的回流路徑不連續會導致信號反射、衰減和失真。2、信號衰減和噪聲干擾&#xff…

almalinux 8 9 升級到指定版本

almalinux 8 update 指定版本 almalinux歷史版 所有版本almalinux最新版 所有版本vault歷史版 almalinux最新版 (https://repo.almalinux.org )地址后面增加不同名稱 echo "delete repos" rm -rf /etc/yum.repos.d/*echo "new almalinux repo" cat <&…

阿里云CDN應對DDoS攻擊策略

阿里云CDN遭遇DDoS攻擊時&#xff0c;可通過以下綜合措施進行應對&#xff0c;保障服務的穩定性和可用性&#xff1a; 1. 啟用阿里云DDoS防護服務 阿里云提供專業的DDoS防護服務&#xff0c;通過流量清洗中心過濾惡意流量&#xff0c;確保合法請求正常傳輸。該服務支持按需選…

CentOS Stream release 9安裝 MySQL(一)

在 CentOS Stream 上安裝 MySQL 的方法與傳統的 CentOS 類似&#xff0c;但由于 CentOS Stream 的軟件包更新策略不同&#xff0c;可能會遇到一些依賴問題。以下是詳細安裝步驟&#xff1a; 1. 添加 MySQL 官方 Yum 倉庫 sudo rpm -Uvh https://dev.mysql.com/get/mysql80-co…

數據結構 | 證明鏈表環結構是否存在

?個人主頁&#xff1a; 鏈表環結構 0.前言1.環形鏈表&#xff08;基礎&#xff09;2.環形鏈表Ⅱ&#xff08;中等&#xff09;3.證明相遇條件及結論3.1 問題1特殊情況證明3.2 問題1普適性證明 0.前言 在這篇博客中&#xff0c;我們將深入探討鏈表環結構的檢測方法&#xff1a;…

數字世界的免疫系統:惡意流量檢測如何守護網絡安全

在2023年全球網絡安全威脅報告中,某跨國電商平臺每秒攔截的惡意請求峰值達到217萬次,這個數字背后是無數黑客精心設計的自動化攻擊腳本。惡意流量如同數字世界的埃博拉病毒,正在以指數級速度進化,傳統安全防線頻頻失守。這場沒有硝煙的戰爭中,惡意流量檢測技術已成為守護網…

【JavaScript】十八、頁面加載事件和頁面滾動事件

文章目錄 1、頁面加載事件1.1 load1.2 DOMContentLoaded 2、頁面滾動事件2.1 語法2.2 獲取滾動位置 3、案例&#xff1a;頁面滾動顯示隱藏側邊欄 1、頁面加載事件 script標簽在html中的位置一般在</body>標簽上方&#xff0c;這是因為代碼從上往下執行&#xff0c;在htm…

Linux : 內核中的信號捕捉

目錄 一 前言 二 信號捕捉的方法 1.sigaction()?編輯 2. sigaction() 使用 三 可重入函數 四 volatile 關鍵字 一 前言 如果信號的處理動作是用戶自定義函數,在信號遞達時就調用這個函數,這稱為捕捉信號。在Linux: 進程信號初識-CSDN博客 這一篇中已經學習到了一種信號…

分布式id生成算法(雪花算法 VS 步長id生成)

分布式ID生成方案詳解:雪花算法 vs 步長ID 一、核心需求 全局唯一性:集群中絕不重復有序性:有利于數據庫索引性能高可用:每秒至少生成數萬ID低延遲:生成耗時<1ms二、雪花算法(Snowflake) 1. 數據結構(64位) 0 | 0000000000 0000000000 0000000000 0000000000 0 |…

函數式編程在 Java:Function、BiFunction、UnaryOperator 你真的會用?

大家好&#xff0c;我是你們的Java技術博主&#xff01;今天我們要深入探討Java函數式編程中的幾個核心接口&#xff1a;Function、BiFunction和UnaryOperator。很多同學雖然知道它們的存在&#xff0c;但真正用起來卻總是不得要領。這篇文章將帶你徹底掌握它們&#xff01;&am…

x265 編碼器中運動搜索 ME 方法對比實驗

介紹 x265 的運動搜索方法一共有 6 種方法,分別是 DIA、HEX、UMH、STAR、SEA、FULL。typedef enum {X265_DIA_SEARCH,X265_HEX_SEARCH,X265_UMH_SEARCH,X265_STAR_SEARCH,X265_SEA,X265_FULL_SEARCH } X265_ME_METHODS;GitHub