Tyspscript中的class

申明一个类 class

class 类名 {
    // class中主要包含两个部分,属性和方法
    属性
    方法
}

实例属性和类属性

  • 实例属性:实例化之后,也就是new之后才能用的属性和方法
  • 类属性(静态属性):class本身自己直接使用的,下面是TS中的属性修饰符
    • static:静态属性,属于类自身不属于实例,只有自身可以访问到
    • readonly:只读属性,只允许读取,不允许修改
    • public:所有属性的默认属性。随意读写
    • private:申明是一个私有属性,不允许在外部访问
    • protected:和private基本一样,也是不允许在外部访问,但是允许在子 类中访问
  • demo
    class Person {
        // 定义实例属性
        name:string = '景天';
        // 在属性前使用static关键字可以定义类属性
        static age:number = 18;
        
        // 定义实例方法
        sayHello() {
            console.log('Hello')
        }
        
        // 定义类方法
        static sayHi() {
            console.log('Hi')
        }
    }
    
    // 实例属性和方法的使用
    class p = new Person()
    console.log(p.name)
    p.sayHello()
    
    // 类属性和方法的使用
    console.log(Person.age)
    Person.sayHi()
    

class中的构造函数(constructor)

  • 常规写法
    class Person {
        name: string
        age: number
        
        // constructor 被称为构造函数
        // 构造函数会在实例对象创建的时候调用
        constructor(name:string,age:number) {
            // 在实例方法中,this就是表示当前的实例
            // 在构造函数中,当前对象就是当前新建的那个对象
            // 可以通过this向新建的对象中添加属性
            this.name = name
            this.age = age
        }
        
        sayHi() {
            // 在实例方法中,可以通过this来表示当前调用方法的对象
            console.log(this)
            console.log(`你好,我是${this.name}`)
        }
    }
    
    class p = new Person('景天',18)
    console.log(p.name,p.age)
    
  • 简写方式
    class Person {
        // 可以把属性的定义写到构造函数的参数中去,所示一种语法糖的写法
        constructor(public name:string, public age:number) {
        }
        
        sayHi() {
            console.log(`你好,我是${this.name}`)
        }
    }
    
    class p = new Person('景天',18)
    console.log(p.name,p.age)
    

class中的继承

  • 使用继承后,子类将会拥有父类所有的方法和属性。
  • 如果子类中和父类中有相同的属性和方法,子类中会覆盖父类的方法。
  • 使用:子类 extends 父类
  • demo
    // 创建一个父类
    class Animal {
        name: string
        
        constructor(name:string) {
            this.name = name
        }
        
        sayHi() {
            console.log('动物们说Hi')
        }
    }
    
    // 狗这个子类继承父类
    class Dog extends Animal {
        age: number
        
        constructor(name:string,age:number) {
            // 如果在子类中写了构造函数,在子类的构造函数中必须要调用下父类的构造函数
            // super就是代表父类中的构造函数
            super(name);
            this.age = age
        }
    
        // 添加一个自己的方法
        run() {
            console.log('我在跑呢')
        }
    }
    
    // 猫这个子类继承父类
    class Cat extends Animal {
        // 子类中也有sayHi方法,会覆盖父类中的方法,使用自己的方法
        sayHi() {
            console.log('喵喵喵喵')
        }
    }
    
    let dog = new Dog('哮天犬',1000)
    dog.sayHi()
    dog.run()
    let cat = new Cat('九命猫妖')
    cat.sayHi()
    

抽象类和抽象方法

  • 抽象类:用abstract开头,这代表是一个抽象类,抽象类和其他类的区别不大,只是不能用来创建对象。
  • 抽象方法:同样abstract开头,抽象方法只能定义在抽象类中,并且子类中必须对抽象方法进行重写。
  • demo
    // 创建一个父类
    /* 
        我们之前创建的父类,除了可以被继承,自己也可以实例化,但是有时候我们就想申明一个父类,不允许实例化。
        那么可以用abstract开头,这代表是一个抽象类,抽象类和其他类的区别不大,只是不能用来创建对象。
        可以说抽象类就是用来创建父类给子类继承的。
        抽象类中可以添加抽象方法。
    */
    abstract class Animal {
        name: string
        
        constructor(name:string) {
            this.name = name
        }
        
        // 定义一个抽象方法,同样abstract开头,没有方法体。
        // 抽象方法只能定义在抽象类中,并且子类中必须对抽象方法进行重写。
        // void:空值
        abstract sayHi():void
    }
    
    class Dog extends Animal {
        sayHi() {
            console.log("汪汪汪")
        }
    }
    
    let a = new Animal() // 这样就会报错,因为不允许实例化
    

接口

  • 和抽象类相比
    • 抽象类的属性值可以是有值得也可以是没值,接口的属性值都是没值的,只定义结构,不考虑实际值
    • 接口中所有的方法都是抽象方法。
    • 使用抽象类,是用extends继承,可以继承父类的方法,也可以重写。接口是使用implements,而且必须满足接口中所有要求
  • demo
    // 定义一个接口
    interface myInter {
        name: string
        
        sayHello():void
    }
    
    // 定义一个类去实现上面的接口,必须满足接口的所有要求
    class Myclass implements myInter {
        name:string
        
        constructor(name:string) {
            this,name = name
        }
        
        sayHello() {
            console.log('Hello')
        }
    }
    
    // 接口如何扩展呢?可以使用extends扩展,但是原来的不会改变
    interface myInter2 extends myInter {
        age: number
    }
    
    // 需要注意的一点是,接口是允许重复的,并不会覆盖,而是会合并
    // 下面这样的,obj就会有两个属性name和age
    interface obj {
        name: string
    }
    interface obj {
        age: number
    }
    

属性的封装

  • 应用场景:有时候我们不想属性简单的暴露出去,也不想被随意更改
  • 简单的封装
    class Person {
        /* 
            TS可以在属性前面添加修饰符
                - static:静态属性,属于类自身不属于实例,只有自身可以访问到
                - readonly:只读属性,只允许读取,不允许修改
                - public:所有属性的默认属性。随意读写
                - private:申明是一个私有属性,不允许在外部访问
                - protected:和private基本一样,也是不允许在外部访问,但是允许在子类中访问
        */
        
        // 私有化两个属性
        private _name:string
        private _age: number
        
        constructor(name:string,age:number) {
            this._name = name;
            this._age = age;
        }
        
        // 提供给外界访问和修改私有属性的方法
        getName() {
            return this._name
        }
        setName(value:string) {
            this._name = value
        }
        getAge() {
            return this._name
        }
        setAge(value:number) {
            if(value > 0) {
                this._age = value
            }
        }
    }
    
    let p = new Person('景天',18)
    
    console.log(p.getName());
    p.setName('雪见')
    console.log(p.getAge());
    p.setAge(17)
    
  • 存取器,比上面简单的封装好的多,这才是常用的方式
    // 使用属性存取器
    class Person {
        // 私有化两个属性
        private _name:string
        paivate _age: number
        
        constructor(name:string,age:number) {
            this._name = name;
            this._age = age;
        }
        
        // 提供给外界访问和修改私有属性的方法
        get name() {
            return this._name
        }
        set name(value:string) {
            this._name = value
        }
        get age() {
            return this._name
        }
        set age(value:number) {
            if(value > 0) {
                this._age = value
            }
        }
    }
    
    let p = new Person('景天',18)
    
    console.log(p.name);
    p.name = '雪见'
    console.log(p.age);
    p.age = 17
    
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容