TS给js扩展了一些概念抽象类、构造函数、继承、接口,让我们一起来了解一下ba~
抽象类
抽象类的特点
- 以abstract开头的类是抽象类和其它类区别不大,只是不能创建对象
- 抽象类是只能用来继承的类,没有办法实例对象
- 抽象类当中可以添加抽象方法
abstract class Animal {
name: string
constructor(name: string) {
this.name = name
}
say() {
console.log('你还好吗')
}
// 定义抽象方法没有方法体,只能定义到抽象类中,子类必须对抽象方法进行重写
abstract listen(): void
}
class Dogs extends Animal {
listen(): void {}
say(): void {
// 在类的方法中super表示当前类的父类
// 在子类方法中引用父类或者父类的实例
super.say()
}
}
const cat = new Dogs('来福')
构造函数
class Person {
name: string
age: number
//构造函数会在对象创建时调用
constructor(name: string, age: number) {
//在实例方法中this表示当前对象的实例
// 在构造函数中当前对象就是当前新建的对象
// 可以通过this向新建的对象中添加属性
this.name = name
this.age = age
}
say() {
console.log('别和我讲法律')
}
}
const dog = new Person('孙悟空', 18)
console.log(dog)
继承
使用extends实现类的继承
class Persons {
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
say() {
console.log('我想上天')
}
}
class Dog extends Persons {
run() {
console.log(`我跑的贼快${this.name}`)
}
}
const dogs = new Dog('旺财', 5)
dogs.run()
接口
- 用接口来定义一个类结构
- 接口用来定义一个类型结构,用来定义一个类型应该包含属性和方法
- 同时接口也可以当成类型声明去使用
- 接口可以在定义类的时候限制类的结构
- 接口中的所有属性都不能有实际的值
- 接口 只定义对象的结构,不考虑实际值,在接口中所有的方法都是抽象方法
interface myInter {
name: string
say(): void
}
// 定义类时,可以使类去实现一个接口,实现接口使类 满足接口的要求
class MyClass implements myInter {
name: string
constructor(name: string) {
this.name = name
}
say(): void {
throw new Error('Method not implemented.')
}
}
属性的封装
- TS可以在属性前添加属性的修饰符(在ts中独有)
- public 修饰的属性可以在任意位置修改(默认值)
- privat 私有属性只能在类内部修改
- protected 受保护的属性,只能在当前类和当前类的子类中使用
- 通过在类中添加方法使私有属性可以被外部访问
class Person {
public _name: string
private _age: number
constructor(name: string, age: number) {
this._name = name
this._age = age
}
// getter用来读取setter用来设置被称为属性读取器
// 定义方法,用来获取age属性
getAge() {
return this._age
}
// 定义方法用来设置age属性
setAge(value: number) {
if (value >= 1) {
this._age = value
}
}
}
const per = new Person('张三', 18)
console.log(per)
/**
* 属性是在对象中设置的,属性可以任意修改
* 属性可以任意修改就会导致对象中的数据变得非常不安全
*/
per._name = '李四'
// 属性“_age”为私有属性,只能在类“Person”中访问(报错)
per._age = 24
console.log(per)
// 私有化后设置和获取属性,如果不想修改就去掉get和set方法使属性为只读状态
console.log(per.getAge())
per.setAge(20)
TS中设置getter和setter的方法
get age() {
return this._age
}
set age(value: number) {
if (value >= 1) {
this._age=value
}
}
per.age=33
protected 受保护的属性的使用方法
class Parent {
protected num: number
constructor(num: number) {
this.num = num
}
}
class Child extends Parent {
test() {
//如果设置私有属性private则访问不到
console.log(this.num)
}
}
const child = new Child(123)
// 属性“num”受保护,只能在类“Parent”及其子类中访问。(报错)
child.num=33
简写方式
可以将属性直接写在构造函数中
class Parent{
constructor(public name:string,public age:number){
}
}
const p = new Parent('张三',18)
泛型
在类型不明确的时候整一个变量,
function fns<K>(a: K): K {
return a
}
// 1.直接调用具有泛型的函数,泛型的值为number(ts的类型推断)
let result = fns(10)
// 手动指定ts泛型
let res = fns<string>('hello')
//2. 泛型可以同时指定多个
function fn2<T, K>(a: T, b: K): T {
console.log(b)
return a
}
fn2<number, string>(123, '456')
// 3.限制泛型范围
interface Inter {
length: number
}
function fn3<T extends Inter>(a: T): number {
// T extends Inter表示泛型T必须时Inter的实现类(子类)不一定传接口
return a.length
}
fn3('123')
//不一定非要用接口
class My<T> {
name: T
constructor(name: T) {
this.name = name
}
}
const people = new My<string>('张三')