TypeScript图形渲染实战2D架构设计与实现:第2章 使用TypeScript实现Doom3词法解析器(3:IDoom3Token接口的实现)

基于Canvas2D的2D篇:京东有售

这段时间有点忙,今天开始又空闲了,那就继续我们的TypeScript之旅!
总览:TypeScript图形渲染实战(2D架构设计和实现)详介
TypeScript图形渲染实战2D架构设计与实现:第2章 使用TypeScript实现Doom3词法解析器(1)
TypeScript图形渲染实战2D架构设计与实现:第2章 使用TypeScript实现Doom3词法解析器(2:Token与Tokenizer)

在上一节中,我们主要介绍了在TypeScript中如何:

  1. import引入模块中定义的类、函数、变量以及类型等,export导出模块中的自定义的接口;
  2. 声明接口方法;
  3. 声明接口的(只读)属性;
  4. ES6中的模版字符串;

今天的文章中,我们将会通过实现IDoom3Token接口来了解TypeScript如下几个要点:

  1. 使用implements关键字实现接口;
  2. 使用class关键字声明类;
  3. 类的三个访问级别:private / protected / public,默认为public;
  4. TypeScript中类型数组的初始化;
  5. 类的成员变量的初始化;
  6. 成员变量的显示断言赋值声明;
  7. constructor关键字实现构造函数

正文:

2.2 IDoom3Token与IDoom3Tokenizer接口的实现

  在上一节中我们声明了IDoom3Token接口和IDoom3Tokenizer接口,本节我们来看一下这两个接口的具体实现过程。我们会发现接口和实现类之间的微妙关系,既:接口规定了要做什么,接口的实现类则规定了应该怎么去做。

2.2.1 Doom3Token类成员变量的声明

  首先我们来看一下IDoom3Token接口的实现类,在TypeScript中使用implements关键字来实现一个接口,代码如下所示:

class Doom3Token implements IDoom3Token {
    private _type : ETokenType ;  // 标识当前token的类型 : NONE / STRING / NUMBER
    private _charArr : string [ ] = [ ] ;  // 字符串数组
    private _val : number ;  // 如果当前的token类型是NUMBER,则会设置该数值,如果是字符串类型,就忽略该变量
}

  上面代码很简单,但是也有几个值得我们关注的地方:

  1. 在TypeScript / JavaScript中,并没有char这个数据类型,都是使用string类型来表示单个字符,我们在变量_charArr中存放的实际是char(一个字符)类型的数据。
  2. 在TypeScript中,有两种声明和实列化(内存分配)类型数组的方式,第一种就是我们上面所使用的方式,另外一种可以使用_charArray : Array < number > = new Array < string > ( )的方式,笔者更喜欢第一种方式来声明类型数组变量,简洁明了少写几个字。
  3. 我们会看到在声明IDoom3Token接口时使用了export关键字来导出接口,但是在实现类Doom3Token中并没有使用export关键字。这是接口的一个很棒的特性:我们只想暴露(export)接口(interface),我们想隐藏类(class)的实现,第三方调用时,只关心接口是怎么使用的,不需要知道具体类是怎么实现的。
  4. TypeScript支持public / protected / private 三个级别的访问修饰符,如果你没有在成员变量前声明访问修饰符,在默认情况下,被定义为public级别。关于三个访问修饰符的区别如下:
  • 被public访问修饰符修饰的成员变量或方法能够被所有类访问。
  • 被protected访问修饰符修饰的成员变量或方法既能被定义它的类也能被继承它的子类访问。
  • 被private访问修饰符修饰的成员变量或方法只能被定义它的类访问,也就是说不能在声明它的类的外部访问。

2.2.2 Doom3Token类变量初始化的问题

  接下来继续来看一下构造函数(constructor关键字)和reset函数,代码如下:

public constructor ( ) {
this . _charArr . length = 0 ;
     this . _type = ETokenType . NONE ;
     this . _val = 0.0 ;
}

public reset ( ) : void {
     this . _charArr . length = 0 ;
     this . _type = ETokenType . NONE ;
     this . _val = 0.0 ;
}

  我们会发现constructor中的代码和reset中的代码一模一样,那么读者可能会问,为什么不在constructor中直接调用reset函数呢?
  其实这里涉及到TypeScript对成员变量初始化的时机点问题。大家可以试一下,如果我们在constructor中调用reset函数,TypeScript编译器会报“xxx属性没有初始化表达式,且未在构造函数中明确赋值。”的错误,如下图2.2所示。

图2.2 TypeScript初始化错误

  从上述错误描述中我们可以知道,TypeScript对于成员变量的初始化有两个时机点,第一个时机点是在成员变量声明时立即进行赋值(初始化),如private _charArr : string [ ] = [ ] ; 这句代码所示,这种称为初始化表达式。
  如果不在成员变量声明时立即赋值的话,那么就只能是在constructor构造函数中进行变量赋值(初始化)。但是你会发现,有时候延迟初始化或重新初始化是很有必要的一种操作。幸运的是,从TypeScript 2.7版本开始支持使用!(感叹号)来进行变量的显示断言赋值声明,我们来修改一下代码,看一下效果,具体代码如下:

// 使用!操作符来进行显示断言赋值声明
private _val  ! : number ;
private _type ! : ETokenType ;

public constructor ( ) {
   // this . _charArr . length = 0 ;
   // this . _type = ETokenType . NONE ;
   // this . _val = 0.0 ;
   this . reset ( ) ;
}

  我们会发现,TypeScript不再报初始化的错误了,是不是很棒的感觉。这是一个很有用的功能,可以让我们灵活的处理变量初始化的问题,因此值得在这里花点时间讨论一下。还是需要强调一点,在使用该变量前一定要初始化变量。

2.2.3 IDoom3Token接口方法的实现

  接下来我们看一下Doom3Token类的其他几个接口方法的实现,具体代码如下:

// 使用get关键字来定义属性,get定义只读属性,set定义只写属性
public get type ( ) : ETokenType {
    return this . _type ;
}
//获取当前token的字符串值
public getString ( ) : string {
    // _charArr数组中存放的都是单个字符序列,例如[ d , o , o , m , 3 ]
    // 我们可以使用数组的join方法将字符串联成字符串
    // 下面会使用join方法后,会返回doom3这个字符串
    return this . _charArr . join ( "" ) ;
}
// 获取当前token的浮点值
public getFloat ( ) : number {
    return this . _val ;
}
// 获取当前token的int类型值
public getInt ( ) : number {
    // 使用parserInt函数
    // 第一个参数是一个字符串类型的数字表示
    // 第二个参数是进制,我们一般用10进制
    return parseInt ( this . _val . toString ( ) , 10 ) ;
}

  我们来看一个字符串比较的接口方法的实现,具体代码如下所示:

public isString ( str : string ) : boolean {
    let count : number = this . _charArr . length ;
    // 字符串长度不相等,肯定不等
    if ( str . length !== count ) {
        return false ;
    }
    // 遍历每个字符
    for ( let i : number = 0 ; i < count ; i++ ) {
     // _charArr数组类型中每个char和输入的string类型中的每个char进行严格比较(!==操作符而不是!=)
     // 只要任意一个char不相等,意味着整个字符串都不相等
        if ( this . _charArr [ i ] !== str [ i ] ) {
            return false ;
        }
    }
    // 完全相等
    return true ;
}

2.2.4 Doom3Token类的非接口方法实现

  至此我们介绍了所有的接口方法的实现以及涉及到的、与TypeScript相关的语言要点,这些接口方法都是被第三方调用的,我们还要增加一些方法,这些方法由实现的内部类(例如IDoom3Tokenizer的实现类Doom3Tokenizer)所调用,但是它们并不需要被公开给第三方使用,下面我们就关注这些方法,具体代码如下所示:

// 下面三个非接口方法被IDoom3Tokenizer接口的实现类Doom3Tokenizer所使用
// 将一个char添加到_charArr数组的尾部
public addChar ( c : string ) : void {
    this . _charArr . push ( c ) ;
}
// 设置数字,并将类型设置为NUMBER
public setVal ( num : number ) : void {
    this . _val = num ;
    this . _type = ETokenType . NUMBER ;
}
//设置类型
public setType ( type : ETokenType ) : void {
    this . _type = type ;
}

今天的内容到此结束,明天我们来解析如何以面向接口的方式实现IDoom3Tokenizer相关的接口方法。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容