TypeScript 的类的基本介绍

类的基本用例

// 类:可以理解为模板,通过模板可以实例化对象
// 面向对象的编程思想
(() => {
    // ts中类定义及使用
    class Person {
        // 定义属性
        name: string
        age: number
        gender: string
        constructor(name: string = '张三', age: number = 13, gender: string = '女') {
            // 更改对象中的属性数据
            this.name = name
            this.age = age
            this.gender = gender
        }
        // 定义实例方法
        sayHi(str: string) {
            console.log(`大家好,我是${this.name},今年已经${this.age}岁了,是个${this.gender}孩子。`, str);
        }
    }
    // ts中使用类,实例化对象,可以直接进行初始化操作
    const person = new Person('11', 15, '男')
    person.sayHi('111');
})()

类的继承

// 继承:类与类直接的关系
// 继承后类与类之间的叫法:
// A类继承了B这个类,那么此刻A类叫子类,B类叫基类
// 子类 --> 派生类
// 父类 --> 超类(父类)
// 一旦发生继承就出现了父子类的关系
(() => {
    // 定义一个类
    class Person {
        // 定义属性
        name: string // 名字
        age: number
        gender: string
        // 定义构造函数
        constructor(name: string = '小明', age: number = 18, gender: string = '男') {
            this.name = name
            this.age = age
            this.gender = gender
        }
        // 定义实例方法
        sayHi(str: string) {
            console.log(`我是${this.name},${str}`);
        }
    }
    // 定义一个类,继承自Person
    class Student extends Person {
        constructor(name: string, age: number, gender: string) {
            // 调用的是父类中的构造函数,使用的是super
            super(name, age, gender)
        }

        // 可以调用父类中的方法
        sayHi() {
            console.log('我是学生中的sayHi方法');
            super.sayHi('haha')
        }
    }
    // 实例化Person
    const person = new Person('大明明', 89, '男');
    person.sayHi('222')
    // 实例化Student
    const stu = new Student('小甜甜', 16, '女')
    stu.sayHi()

    // 总结:类和类之间如果要有继承关系,需要使用extends关键字
    // 子类可以调用父类中的关键字,但是super关键字(包括调用父类中的实例方法,也可以使用super)
    // 子类中可以重写父类中的方法
})()

多态

// 多态:父类型的引用指向子类型的对象,不用类型的对象针对不同的方法,产生了不同的行为
(() => {
    // 定义一个父类
    class Animal {
        // 定义一个属性
        name: string
        // 定义一个构造函数
        constructor(name: string) {
            this.name = name
        }
        // 实例方法
        run(distance: number = 0) {
            console.log(`跑了${distance}这么远的距离`, this.name);
        }
    }
    // 定义一个子类
    class Dogs extends Animal {
        // 构造函数
        constructor(name: string) {
            // 调用父类的构造函数实现了类中属性的初始化操作
            super(name)
        }
        // 实例方法,重写父类中的实例方法
        run(distance: number = 5) {
            console.log(`跑了${distance}这么远的距离`, this.name);
        }
    }
    // 定义一个子类
    class Pig extends Animal {
        // 构造函数
        constructor(name: string) {
            // 调用父类的构造函数实现了类中属性的初始化操作
            super(name)
        }
        // 实例方法,重写父类中的实例方法
        run(distance: number = 10) {
            console.log(`跑了${distance}这么远的距离`, this.name);
        }
    }
    // 实例化父类对象
    const ani: Animal = new Animal('动物')
    ani.run()
    // 实例化子类对象
    const dog: Dogs = new Dogs('大黄')
    dog.run()

    // 实例化子类对象
    const pig: Pig = new Dogs('八戒')
    pig.run()

    // 父类和子类的关系:父子关系,此时,父类类型创建子类的对象
    // 父类型的引用指向子类型的对象
    const dog1: Animal = new Dogs('小黄')
    dog1.run()
    const pig1: Animal = new Pig('小猪')
    pig1.run()

    function showRun(ani: Animal) {
        ani.run()
    }
    showRun(dog1)
    showRun(pig1)
})()

公共,私有与受保护的修饰符

默认为 public

在上面的例子里,我们可以自由的访问程序里定义的成员。 如果你对其它语言中的类比较了解,就会注意到我们在之前的代码里并没有使用 public 来做修饰;例如,C# 要求必须明确地使用 public 指定成员是可见的。 在 TypeScript 里,成员都默认为 public

你也可以明确的将一个成员标记成 public。 我们可以用下面的方式来重写上面的 Animal 类:

private

当成员被标记成 private 时,它就不能在声明它的类的外部访问。

protected

protected 修饰符与 private 修饰符的行为很相似,但有一点不同,protected成员在派生类中仍然可以访问。例如:

// 修饰符(类中的成员装饰符):主要是描述类中的成员(属性,构造函数,方法)的可访属性
// 类中的成员都有自己默认的访问修饰符 public
// public 修饰符,类中的成员默认的修饰符,代表的是公共的,任何位置都可以访问类中的成员
// private修饰符,其中类的成员如果使用private来修饰,那么外部无法访问这个成员数据的,当然子类中也是无法访问成员数据的
// protected 修饰符 外部是无法访问的,在子类内可以访问该成员

(() => {

    // 定义一个类
    class Person {
        // 属性 public 修饰了属性成员
        // public name: string

        // 属性 private 修饰属性成员
        // private name: string

        // 属性 protected 修饰属性成员
        protected name: string
        public constructor(name: string) {
            // 更新属性
            this.name = name;
        }
        // 方法
        public eat() {
            console.log('123');
        }
    }

    // 再次定义一个子类
    class Student extends Person {
        constructor(name: string) {
            super(name)
        }
        play() {
            console.log('567', this.name);

        }
    }

    // 实例化对象
    const per = new Person('456')
    // 在类的外部可以访问类的属性
    // console.log(per.name);
    per.eat()
    const stu = new Student('12');
    stu.play();
    // console.log(stu.name);

})()

readonly

// readonly修饰符:首先是一个关键字,对类中的属性成员进行修饰,修饰后,该属性成员就不能在外部随意修改
// 构造函数中可以对只读的属性成员的数据进行修改
// 构造函数中没有任何的参数,类中的属性成员此时已经使用readonly进行修饰,那么外部是不能对这个属性值进行修改的
// 构造函数的参数可以使用readonly进行修饰,一旦修饰了,那么该类中就有了这个只读的属性,外部可以访问,但是不能修改
// 构造函数的参数可以使用public及pricvate和protected,无论是哪个进行修饰,该类中会自动添加一个属性成员

(() => {
    // readonly 修饰类中的成员属性

    // 定义一个类型
    // class Person {
    //     readonly name: string = '100' // 初始值
    //     // 构造函数
    //     constructor(name: string) {
    //         this.name = name
    //     }
    //     sayHi() {
    //         console.log('123', this.name);
    //         // 类中的普通方法中也是不能修改readonly修饰成员属性值
    //         // this.name = '23';
    //     }
    // }
    // // 实例化对象
    // const person: Person = new Person('56');
    // console.log(person);
    // console.log(person.name);
    // // 在外部无法修改内部的只读属性
    // // person.name = '123565';
    // console.log(person.name);


    // readonly 修饰类中的构造函数的参数(参数属性)

    class Person {
        // 构造函数中的name参数,一旦使用readonly进行修饰后,那么该name参数可以叫做参数属性
        // Person中就有了一个name属性
        // 外部无法修改类中的name属性成员值
        // constructor(readonly name: string) {
        //     // this.name = name
        // }
        // 构造函数中的name属性,一旦使用public进行修改后,那么Person类中就有一个公共的name成员属性成员   
        // 同时这里也可以替换为private和protected属性
        constructor(public name: string) {
            // this.name = name
        }

    }
    // 实例化对象
    const person: Person = new Person('56');
    console.log(person);
    console.log(person.name);
    // 在外部无法修改内部的只读属性
    // person.name = '123565';
    console.log(person.name);
})()

存取器 

// 存取器:让我们可以有效的控制对 对象中的成员访问,通过getter和setter来进行操作

(() => {
    // 外部可以传入姓氏和名字数据,同时使用set和get控制姓名数据,外部也可以进行修改操作
    class Person {
        firstName: string  // 姓氏
        lastName: string   // 名字
        constructor(firstName: string, lastName: string) {
            this.firstName = firstName;
            this.lastName = lastName;
        }

        // 姓氏的成员属性(外部可以访问,也可以修改)

        // 读取器--负责读取数据
        get fullName() {
            return this.firstName + "_" + this.lastName
        }

        // 设置值--负责设置数据(修改)
        set fullName(val) {
            // 姓名--把姓氏和名字获取到重新赋值给firstName和lastName
            let names = val.split("_");
            this.firstName = names[0];
            this.lastName = names[names.length - 1];
        }
    }


    // 实例化对象
    const person: Person = new Person("东方", "不败")
    console.log(person.fullName)   // 名字再获取中的时候会调用get
    person.fullName = "诸葛_孔明"   // 在设置数据的时候会触发set
    console.log(person.fullName)
})()

 

静态属性

// 静态成员:在类中通过static修饰的属性或者方法,那么就是静态的属性或者静态的方法,也成为静态成员
// 静态成员在使用的时候是通过类名的这种 语法来调用的
(() => {
    // 定义一个类
    class Person {
        // 类中默认有一个内置的name属性,在设置属性name时会出现错误
        static name1: string = '123'
        // 构造函数是不能通过static进行修饰的
        constructor() {
            // 此时this是实例对象,name1是静态属性,不同通过实例对象直接调用静态属性来使用
            // this.name1 = name
        }
        // 静态方法
        static sayHi() {
            console.log('123456');
        }
    }
    // 实例化对象
    // const person: Person = new Person()
    // 通过实例对象调用的属性(实例属性)
    // console.log(person.name);
    // 通过实例对象调用的方法(实例方法)
    // person.sayHi()

    // 通过类名.静态属性的方式来访问该成员数据
    console.log(Person.name1);
    // 通过类名.静态属性的方式来设置该成员数据
    Person.name1 = '45'
    console.log(Person.name1);
    // 通过类名.静态属性的方式来调用内部的静态方法
    Person.sayHi()
})()

抽象类

// 抽象类:包含抽象方法(抽象方法一般没有任何的具体内容实现),也是可以包含实例方法,抽象类是不能被实例化,为了让子类进行实例化及实现内部的抽象方法
// 抽象类的目的或作用都是为了子类服务
(() => {
    // 定义一个抽象类
    abstract class Animal {
        // abstract name: string    // 没有必要有一个抽象属性让子类去实现
        // 抽象方法
        abstract eat()
        // 抽象方法不能有具体实现,例如:
        // abstract eat(){
        //     console.log('123');
        // }
        // 实例方法
        sayHi() {
            console.log('你好');
        }
    }
    // 定义一个子类(派生类)Dog
    class Dog extends Animal {
        name: string = 'dog'
        // 重新的实现抽象类的方法,此时这个方法就是当前的Dog类的实例方法
        eat() {
            console.log('eat..');
        }
    }
    // 实例化Dog对象
    const dog: Dog = new Dog()
    dog.eat()
    // 调用的是抽象类中的实例方法
    dog.sayHi()
    console.log(dog.name);

    // 不能实例化抽象类的对象
    // const ani: Animal = new Animal()

})()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值