ArkTS-接口、泛型、空安全

接口

接口声明引入新类型。接口是定义代码协定的常见方式。

任何一个类的实例只要实现了特定接口,就可以通过该接口实现多态。

接口通常包含属性和方法的声明

interface Style {
  color: string // 属性
}
interface AreaSize {
  calculateAreaSize(): number // 方法的声明
  someMethod(): void;     // 方法的声明
}

实现接口的类示例:

// 接口:
interface AreaSize {
  calculateAreaSize(): number // 方法的声明
  someMethod(): void;     // 方法的声明
}

// 实现:
class RectangleSize implements AreaSize {
  private width: number = 0
  private height: number = 0
  someMethod(): void {
    console.log('someMethod called');
  }
  calculateAreaSize(): number {
    this.someMethod(); // 调用另一个方法并返回结果
    return this.width * this.height;
  }
}
  • 接口属性

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

属性字段只是getter/setter对的便捷写法。以下表达方式是等价的:

interface Style {
  color: string
}

interface Style {
  get color(): string
  set color(x: string)
}

实现接口的类也可以使用以下两种方式:

interface Style {
  color: string
}

class StyledRectangle implements Style {
  color: string = ''
}
interface Style {
  color: string
}

class StyledRectangle implements Style {
  private _color: string = ''
  get color(): string { return this._color; }
  set color(x: string) { this._color = x; }
}
  • 接口继承

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

interface Style {
  color: string
}

interface ExtendedStyle extends Style {
  width: number
}

继承接口包含被继承接口的所有属性和方法,还可以添加自己的属性和方法。

泛型类和接口

  • 类和接口可以定义为泛型,将参数添加到类型定义中,如以下示例中的类型参数Element:
class CustomStack {
  public push(e: Element):void {
    // ...
  }
}
  • 要使用类型CustomStack,必须为每个类型参数指定类型实参:
let s = new CustomStack();
s.push('hello');
  • 编译器在使用泛型类型和函数时会确保类型安全。参见以下示例:
let s = new CustomStack();
s.push(55); // 将会产生编译时错误
  • 泛型约束

泛型类型的类型参数可以被限制只能取某些特定的值。例如,MyHashMap这个类中的Key类型参数必须具有hash方法。

interface Hashable {
  hash(): number
}
class MyHashMap {
  public set(k: Key, v: Value) {
    let h = k.hash();
    // ...其他代码...
  }
}
  • 泛型函数

使用泛型函数可编写更通用的代码。比如返回数组最后一个元素的函数:

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

如果需要为任何数组定义相同的函数,使用类型参数将该函数定义为泛型:

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

现在,该函数可以与任何数组一起使用。

在函数调用中,类型实参可以显式或隐式设置:

// 显式设置的类型实参
last(['aa', 'bb']);
last([1, 2, 3]);

// 隐式设置的类型实参
// 编译器根据调用参数的类型来确定类型实参
last([1, 2, 3]);
  • 泛型默认值

泛型类型的类型参数可以设置默认值。这样可以不指定实际的类型实参,而只使用泛型类型名称。下面的示例展示了类和函数的这一点。

class SomeType {}
interface Interface  { }
class Base  { }
class Derived1 extends Base implements Interface { }
// Derived1在语义上等价于Derived2
class Derived2 extends Base implements Interface { }

function foo(): T {
  // ...
}
foo();
// 此函数在语义上等价于下面的调用
foo();

空安全

默认情况下,ArkTS中的所有类型都是不可为空的,因此类型的值不能为空。这类似于TypeScript的严格空值检查模式(strictNullChecks),但规则更严格。

在下面的示例中,所有行都会导致编译时错误:

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?: Person

  setSpouse(spouse: Person): void {
    this.spouse = spouse;
  }

  getSpouseNick(): string | null | undefined {
    return this.spouse?.nick;
  }

  constructor(nick: string) {
    this.nick = nick;
    this.spouse = undefined;
  }
}

说明:getSpouseNick的返回类型必须为string | null | undefined,因为该方法可能返回null或者undefined。

可选链可以任意长,可以包含任意数量的?.运算符。

说明:getSpouseNick的返回类型必须为string | null | undefined,因为该方法可能返回null或者undefined。

可选链可以任意长,可以包含任意数量的?.运算符。

在以下示例中,如果一个Person的实例有不为空的spouse属性,且spouse有不为空的nick属性,则输出spouse.nick。否则,输出undefined:
阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.1024c.cn/archives/22021,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?