You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
TypeScript一次只能继承一个类,不支持继承多个类,但TypeScript支持多重继承(C继承B,B继承A)子类除了不能继承父类的私有成员,其它的都可以继承。classme{publicname:stringpublicage:numberpublicconstructor(name:string,age:number){this.name=namethis.age=age}publicsayHello(){console.log('你好!我叫'+this.name+',今年'+this.age+'岁');}}//mySon类 继承(复制)了 me类 里的所以属性和方法classmySonextendsme{publicyangzi:string='帅'publiczhuanqian(){console.log('我会赚钱');}}//因为继承了me类的属性和方法,所以可以使用me类中的constructor构造方法
let son:mySon=newmySon('我儿子',10);//使用继承自me类里面的sayhello方法son.sayHello();//打印:你好!我叫我儿子,今年10岁//使用mySon类中的zhuanqian方法son.zhuanqian();//打印:我会赚钱
类继承属性和方法的重写
子类可以继承父类的属性和方法,并且子类可以重写(覆盖)父类的非私有属性和方法。父类中的属性和方法如果被声明为private,则它们不能在子类中被访问或重写。在子类中,可以使用super关键字来访问父类的属性和方法。子类可以重写(实际上是提供自己的实现)父类的构造函数。在子类的构造函数中,通常需要使用super()来调用父类的构造函数,以确保父类的初始化代码得到执行。classme{publicname:stringpublicage:numberpublicconstructor(name:string,age:number){this.name=namethis.age=age}publicsayHello(){console.log('你好!我叫'+this.name+',今年'+this.age+'岁');}}//mySon继承(复制)了me的所以属性和方法classmySonextendsme{publicyangzi:string='帅'constructor(name:string,age:number){//重写类的,构造函数super(name,age)//调用父类构造函数}publicsayHello(){//重写me类中的sayHello方法super.sayHello();//调用me类中的sayHello方法console.log('我是'+this.name+',我在,mySon类中');}publiczhuanqian(){console.log(this.name,'我会赚钱');}}
let son:mySon=newmySon('我儿子',10);son.sayHello();//使用了mySon中重写后的sayHello()方法son.zhuanqian();//使用mySon类中的zhuanqian方法
类继承属性和方法重写注意事项
classA{name: stringreadonlyage: numberprivatemoney: numberprotectedcar: stringconstructor(name: string,age: number,money: number){this.name=name;this.age=age;this.money=money;}say(text: string): string{letstr: string=`我是${this.name}。我今年${this.age}。我有${this.money}元。`;console.log(str);returnstr;}}// class B extends A {// name:number //报错。类型“B”中的属性“name”不可分配给基类型“A”中的同一属性。不能将类型“number”分配给类型“string”。// }// class B extends A {// protected name:string //报错。类“B”错误扩展基类“A”。属性“name”在类型“B”中受保护,但在类型“A”中为公共属性。// }// class B extends A {// private name:string //报错。类“B”错误扩展基类“A”。属性“name”在类型“B”中是私有属性,但在类型“A”中不是。// }// //未报错// class B extends A {// readonly name:string// }// class B extends A {// money:number //报错。类“B”错误扩展基类“A”。属性“money”在类型“A”中是私有属性,但在类型“B”中不是。// }// class B extends A {// private money:number //报错。类“B”错误扩展基类“A”。类型具有私有属性“money”的单独声明。// }// class B extends A {// car:number //报错。类型“B”中的属性“car”不可分配给基类型“A”中的同一属性。不能将类型“number”分配给类型“string”。// }// //未报错// class B extends A {// car:string// }// //未报错// class B extends A {// public car:string// }// //未报错// class B extends A {// protected car:string// }// //未报错// class B extends A {// protected readonly car:string// }// class B extends A {// private car:string //报错。类“B”错误扩展基类“A”。属性“car”在类型“B”中是私有属性,但在类型“A”中不是。// }// class B extends A {// say:string //报错。类型“B”中的属性“say”不可分配给基类型“A”中的同一属性。不能将类型“string”分配给类型“(text: string) => void”。// }// class B extends A {// //报错。类型“B”中的属性“say”不可分配给基类型“A”中的同一属性。不能将类型“(name: string, age: number) => string”分配给类型“(text: string) => string”。// say(name:string,age:number):string{// return '字符串'// }// }// //未报错// class B extends A {// say(name:string):string{// return '字符串'// }// }// class B extends A {// // 报错// // 类型“B”中的属性“say”不可分配给基类型“A”中的同一属性。// // 不能将类型“(name: number) => string”分配给类型“(text: string) => string”。// // 参数“name”和“text” 的类型不兼容。// // 不能将类型“string”分配给类型“number”。// say(name:number):string{// return '字符串'// }// }// class B extends A {// // 类型“B”中的属性“say”不可分配给基类型“A”中的同一属性。// // 不能将类型“(name: string) => void”分配给类型“(text: string) => string”。// // 不能将类型“void”分配给类型“string”。// say(name:string):void{// }// }
instanceof运算符
instanceof(instanceof)运算符用于判断对象是否是指定的类型classPerson{}varobj=newPerson()varisPerson=objinstanceofPerson;console.log("obj 对象是 Person 类实例化来的吗? "+isPerson);//true
implements是用于实现接口的,类必须提供接口中定义的所有方法的具体实现。classAnimal{}interfaceRunnable{run(): void;}interfaceSpeakable{speak(): void;}//Dog 类继承了 Animal 类并实现了 Runnable 和 Speakable 两个接口。classDogextendsAnimalimplementsRunnable,Speakable{run(){console.log(`The dog is running.`);}speak(){console.log(`The dog barks.`);}}//如下报错,因为 Dog类 中缺少 speak方法。//接口Speakable 中规定需要存在该方法。classDogextendsAnimalimplementsRunnable,Speakable{run(){console.log(`The dog is running.`);}}
命名空间
命名空间,用来解决重名问题。假设这样一种情况,当一个班上有两个名叫小明的学生时,为了明确区分它们,我们在使用名字之外,不得不使用一些额外的信息,比如他们的姓氏(王小明,李小明)为了在外部可以调用命名空间中的类和接口,需要在类和接口前添加export关键字。namespacefat{exportclassdehua{publicname:string='胖德华'sayHello(){console.log('我是'+this.name);}}}namespacethin{exportclassdehua{publicname:string='瘦德华'sayHello(){console.log('我是'+this.name);}}}
let fatDehua:fat.dehua=newfat.dehua()
let thinDehua:thin.dehua=newthin.dehua()fatDehua.sayHello();//我是胖德华thinDehua.sayHello();//我是瘦德华
泛型
泛型是一种编程语言特性,允许在定义函数、类、接口等时,使用占位符来表示类型,而不是具体的类型。泛型最重要的功能是,代码重用,这样可以编写与特定类型无关的通用代码,提高代码的复用性。//泛型函数案例//使用泛型来创建一个可以处理不同类型数据的函数//如下,identity是一个泛型函数,使用 T 表示泛型类型functionidentity<T>(arg: T): T{returnarg;}//使用string代表Tletresult=identity<string>("Hello");console.log(result);//Hello//使用number代表TletnumberResult=identity<number>(42);console.log(numberResult);//42//如下,comb是一个泛型函数,使用 T 表示泛型类型functioncomb<T>(arr:T[]):T[]{returnarr}//泛型接口案例//这里定义了一个泛型接口Pair,它有两个类型参数 T 和 U。interfacePair<T,U>{first: T;second: U;}//使用string代表T。使用number代表U。letpair: Pair<string,number>={first: "hello",second: 42};console.log(pair);// { first: 'hello', second: 42 }//泛型 类 案例//使用 T 表示泛型类型。classBox<T>{privatevalue: T;constructor(value: T){this.value=value;}getValue(): T{returnthis.value;}}//使用string代表TletstringBox=newBox<string>("TypeScript");console.log(stringBox.getValue());//TypeScript
类型断言,是一种手段,允许开发者在代码中“断言”某个值的类型,也就是告诉编译器此处的值是什么类型。TypeScript一旦发现存在“类型断言”,就不再对该值进行类型推断,而是直接采用断言给出的类型。这种做法的实质是,允许开发者在某个位置“绕过”编译器的类型推断,让本来通不过类型检查的代码能够通过,避免编译器报错。这样虽然削弱了TypeScript类型系统的严格性,但是为开发者带来了方便,毕竟开发者比编译器更了解自己的代码。类型断言并不是真的改变一个值的类型,而是提示编译器,应该如何处理这个值typeT='a'|'b'|'c';letfoo='a';letbar:T=foo;//报错,原因是 TypeScript 推断变量foo的类型是string,而变量bar的类型是'a'|'b'|'c',前者(string)是后者('a'|'b'|'c')的父类型。父类型不能赋值给子类型,所以就报错了。//上面报错,可以使用‘断言’解决报错。letbar:T=fooasT;//这里foo as T表示告诉编译器,变量foo的类型断言为T,所以这一行不再需要类型推断,然后编译器直接把foo的类型当作T,所以就不报错了。letbar:T=<T>foo;//foo as T是第一种断言语法。这里<T>foo是第二种断言语法。
//.tsfunctionaFun(){{//块级作用域
let a:string='a'console.log(a);}console.log(a);}aFun();//编译成.js后functionaFun(){{//块级作用域vara:string='a'//这里let会变成var,在使用中需注意console.log(a);}console.log(a);}aFun();