四.类——Class

ts里面的类与js的类大同小异,无非是做了一些了类型校验和功能拓展。

基本使用

我们使用class关键字来声明一个类,并进行一些实例属性与方法的声明。

class Dog {
	//定义几个实例属性
    name: string = '小狗'
    age: number = 5
    //定义一个实例方法,该方法会绑定在类的原型对象上
    sayHi() {
        console.log('Hi')
    }
}

let dog = new Dog() //Dog: {"name": "小狗","age": 5} 
dog.sayHi() //hi

手动设置属性值

上面代码里我们的实例属性是写死的,实用性并不高,我们使用constructor尝试进行手动赋值操作。

class Dog {
    name: string
    age: number
    constructor(name: string, age: number) {
        this.age = age
        this.name = name
    }
    sayHi() {
        console.log('Hi')
    }
}
let dog = new Dog('富贵', 5)
console.log(dog) //Dog: {"name": "小狗","age": 5} 
dog.sayHi() //hi

设置静态属性

我们也可以给类设置一些静态属性和方法,这些属性方法不需要通过实例,而可以直接通过类使用。

class Dog {
    static gender: string = '雌'
    static getGender() {
        console.log('我的性别是' + Dog.gender)
    }
}
console.log(Dog.gender) // '雌'
Dog.getGender()  // '我的性别是雌'

继承

说到类就不得不说继承。继承往往可以使我们将一些公共方法或者属性进行抽离封装,减少代码复用率。

class Animal {
    type: string
    gender: boolean
    constructor(type: string, gender: boolean) {
        this.type = type
        this.gender = gender
    }
}

class Dog extends Animal {
    age: number
    constructor(gender: boolean, age: number) {
        super('dog', gender)
        this.age = age
    }
}


let dog: Dog = new Dog(true, 5)
console.log(dog)
// {
//   "type": "dog",
//   "gender": true,
//   "age": 5
// }

继承的过程中我们可能会对一些属性或方法进行重写操作

class Animal {
    type: string
    gender: boolean
    constructor(type: string, gender: boolean) {
        this.type = type
        this.gender = gender
    }
    sayHi() {
        console.log('动物再叫')
    }
}

class Dog extends Animal {
    age: number
    constructor(gender: boolean, age: number) {
        super('dog', gender)
        this.age = age
    }
    sayHi() {
        console.log('小狗在叫')
    }
}

let dog: Dog = new Dog(true, 5)
dog.sayHi() //小狗在叫

修饰符

public(默认修饰符)
我们在正常定义类的情况下,里面的属性和方法默认都是public。也就是说默认定义的方法和属性是公开的,可以在类的内部和外部使用。

class Dog {
    name: string = '小狗'
    age: number = 5
    sayHi() {
        console.log(this.name'说Hi') //直接在类的内部使用name属性
    }
}

let dog = new Dog() //Dog: {"name": "小狗","age": 5} 
dog.name // 直接在类的外部使用name属性

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

class Dog {
    private name: string = '小狗'
    sayHi() {
        console.log(this.name + '说Hi') //直接在类的内部使用name属性
    }
}

let dog = new Dog() //Dog: {"name": "小狗","age": 5} 
dog.sayHi() // 小狗说Hi
dog.name // Property 'name' is private and only accessible within class 'Dog'.

即使是继承的类,也是不能访问的。

class Animal {
    private type: string
    gender: boolean
    constructor(type: string, gender: boolean) {
        this.type = type
        this.gender = gender
    }
}

class Dog extends Animal {
    age: number
    constructor(gender: boolean, age: number) {
        super('dog', gender)
        this.age = age
        console.log(this.type) //Property 'type' is private and only accessible within class 'Animal'.
    }
}

protected(类私有的)
protectedprivate及其相似,但是他定义出的属性和方法是可以在被继承的类里访问的。

class Animal {
    protected type: string
    gender: boolean
    constructor(type: string, gender: boolean) {
        this.type = type
        this.gender = gender
    }
}

class Dog extends Animal {
    age: number
    constructor(gender: boolean, age: number) {
        super('dog', gender)
        this.age = age
        console.log(this.type)  //dog
    }
}

readonly(只读的)
只读实现必须在类的属性定义或者constructor里面赋值。

参数属性

我们发现上面的类里面,我们每次在构造函数constructor里面声明一个属性时,都需要先在外面进行类型声明,然后再到构造函数上面声明形参才可以在内部进行赋值操作,但是我们完全可以使用参数属性声明类型声明这一步。

class Animal {
    constructor(protected type: string, public gender: boolean) {
        this.type = type
        this.gender = gender
    }
}

我们通过直接在构造函数上使用修饰符的方式,省略了类型声明的这一步,直接在构造函数里面进行赋值操作。

get/Set(存取器)

class Person {
    constructor(public name: string, public age: number) {
        this.name = name
        this.age = age
    }
}
let user: Person = new Person('fufu', 20)
user.age = 1000

上面代码里我们定义了一个Person类,这个类里有一个age属性,我们生成实例后可以随意修改这个年龄甚至修改到10000年,这显然是不合理的。我们可以使用get/set对属性进行存取设置。

class Person {
    constructor(public name: string, private _age: number) {
        this.name = name
        this._age = _age
    }
    get getAge() {
        return this._age
    }
    set setAge(num: number) {
        if (num > 120) {
            console.log('数字太大啦!')
        }
    }
}
let user: Person = new Person('fufu', 20)
user.setAge = 130 //数字太大啦!
console.log(user.getAge) // 20

抽象类

很多时候我们并不希望所有类都能被拿去创建实例,例如我们有一个animal类,我们只希望他被其他类继承,而不希望有人直接用它创建实例,这个时候我们就需要用到抽象类。

abstract class Animal {
    constructor(public breed: string) {
        this.breed = breed
    }
}

class Dog extends Animal {
    constructor() {
        super('dog')
    }
}
let animal: Animal = new Animal('dog') //Cannot create an instance of an abstract class.
let dog: Dog = new Dog()
console.log(dog.type) // 'dog'

抽象类中还可以定义抽象方法,抽象方法不包含具体实现并且必须在派生类中实现。 抽象方法的语法与接口方法相似。 两者都是定义方法签名但不包含方法体。

abstract class Animal {
    constructor(protected breed: string) {
        this.breed = breed
    }
    abstract sayHi(): void
}

class Dog extends Animal {
    constructor() {
        super('dog')
    }
    sayHi() {
        console.log(this.breed + '在叫!')
    }
}

let dog: Dog = new Dog() 
dog.sayHi() // dog在叫!

注意我们在定义属性的时候必须要赋初始值或者在constructor去赋值,你可以使用!或者?进行断言或者表面它是可选的。

class Dog {
    name?: string
    age!: number
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值