本文介绍了TS类的使用,从初识class到构造函数再到继承然后说super,还说到了abstract抽象类以及private,public,protected 的区别。
初识class类
构造函数constructor
继承extends
super方法
抽象类abstract
private、public和protected区别
interface接口
泛型
使用class 关键字来定义一个类,对象中主要包含了两个部分:属性和方法
class Person{
//这个类四个个属性
/*
1、如果属性用static修饰的话(默认为public),表示静态属性 不能通过实例对象访问到该属性,
需要通过类去访问,比如 Person.gender
2、如果属性用readonly修饰的话,表示该属性只读,无法修改该属性
*/
name:string = 'C罗'
age:number = 37
static gender:string = '男'
readonly hobby:string = '足球'
//方法
/*
通过static修饰该方法(默认为public),表示静态方法 ,不能通过实例对象访问到该方法
需要通过类去访问 ,比如 Person.sayHello()
*/
sayHello(){
console.log('我是public方法')
}
static sayHello1(){
console.log('我是static静态方法')
}
}
//创建Person的实例对象
var per = new Person(); //per就是Person类的实例对象
console.log(per); //Person {name: 'C罗', age: 37}
//static 修饰的属性 需要用类来访问
console.log(Person.gender); //男
//public修饰的属性
console.log(per.name); //C罗
//public修饰的方法
console.log(per.sayHello()); // 有人访问了我'
//static修饰的方法 需要用类来访问
console.log(Person.sayHello1()); //我是静态方法,我只能通过Person访问
//readonly(只读)修饰的属性是无法修改的 ,下面代码会报错
// per.hobby = '篮球'
构造函数 constructor
class Dog{
/*
构造函数
constructor 这个就是类的构造函数
调用时间:对象创建时调用
限制:仅能一个构造函数
this指向:
1、在实例方法中,this就表示当前当前的实例
2、在构造函数中的当前对象就是新建的那个对象
3、可以通过this向新建的对象中添加属性
*/
name:string
age:number
constructor(name:string,age:number){
this.name = name
this.age = age
}
bark(){
console.log('汪汪汪...')
}
}
const dog = new Dog('小黑',2)
const dog2 = new Dog('小白',3)
console.log(dog) //Dog {name: '小黑', age: 2}
console.log(dog2) //Dog {name: '小白', age: 3}
console.log(dog.bark()) //汪汪汪.
继承extends
/*
* Dog extends Animal
* - 此时,Animal被称为父类,Dog被称为子类
* - 使用继承后,子类将会拥有父类所有的方法和属性
* - 通过继承可以将多个类中共有的代码写在一个父类中,
* 这样只需要写一次即可让所有的子类都同时拥有父类中的属性和方法
* 如果希望在子类中添加一些父类中没有的属性或方法直接加就行
* - 如果在子类中添加了和父类相同的方法,则子类方法会覆盖掉父类的方法
* 这种子类覆盖掉父类方法的形式,我们称为方法重写
*
*/
class Animal{
name:string
age:number
//构造函数
constructor(name:string,age:number){
this.name = name
this.age = age
}
// 自定义方法
sayHello(){
console.log('动物在叫~')
}
}
class Dog extends Animal{
// 重写父类方法
sayHello(): void {
console.log('汪汪汪')
}
}
class Cat extends Animal{
//重写父类方法
sayHello(): void {
console.log('喵喵喵')
}
}
const dog = new Dog('旺财',4)
const cat = new Cat('咪咪',3)
console.log(dog) //Dog {name: '旺财', age: 4}
console.log(dog.sayHello()) //汪汪汪
console.log(cat) //Cat {name: '咪咪', age: 3}
console.log(cat.sayHello()) //喵喵喵
super方法
/*
super: 调用父类构造函数
场景:如果在子类中写了构造函数,在子类构造函数中"必须"对父类的构造函数进行调用
在类的方法中 super就表示当前类的父类 super.sayHello();
*/
class Animal{
name:string
age:number
constructor(name:string,age:number){
this.name = name
this.age = age
}
sayHello(){
console.log('动物在叫~')
}
}
class Dog extends Animal{
//子类构造函数
constructor(name:string,age:number){
super(name,age)
this.age = age
}
//重写父类方法
sayHello(): void {
super.sayHello()
console.log('汪汪汪')
}
}
const dog = new Dog('旺财',2)
console.log(dog) //Dog {name: '旺财', age: 2}
console.log(dog.sayHello()) //动物在叫~ 汪汪汪
抽象类abstract
/*
* 以abstract开头的类是抽象类,
* 抽象类和其他类区别不大,只是不能用来创建对象
* 抽象类就是专门用来被继承的类
* 抽象类中可以添加抽象方法
*/
abstract class Animal{
name: string;
constructor(name: string) {
this.name = name;
}
/*
* 定义一个抽象方法
* 抽象方法使用 abstract开头,没有方法体
* 抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
*/
abstract sayHello():void //只能这样写 不能有具体实现什么 否则报错
}
class Dog extends Animal{
//注意:必须要重写父类,抽象的方法,不然会报错
sayHello():void {
console.log('汪汪汪')
}
}
// const an = new Animal() //会报错 ,无法创建抽象类的实例
private、public和protected区别
(function(){
// TS可以在属性前添加属性的修饰符
/*
* public 修饰的属性可以在任意位置访问(修改)默认值
* private 私有属性,私有属性只能在类内部进行访问(修改)
* - 通过在类中添加方法使得私有属性可以被外部访问
* protected 受保护的属性,只能在当前类和当前类的子类中访问(修改)
*
*/
class Person{
private _name:string
private _age:number
constructor(name:string,age:number){
this._name = name
this._age = age
}
setName(value){
this._name = value
}
getName(){
return this._name
}
/*
* 实际上,上面的两个方法 官方已经给了我们两个标准的方法
* TS中设置getter方法的方式
* 此时再使用per.name时,实际上是调用了get name()方法!
*/
// get name() {
// console.log('get name()执行了!!');
// return this._name;
// }
// // TS中设置setter方法的方式
// // 此时再使用per.name = xxx时,实际上是调用了set name()方法!
// set name(value) {
// console.log('set name()执行了!!');
// this._name = value;
// }
}
const per = new Person('内马尔',32)
console.log(per) //Person {_name: '内马尔', _age: 32}
// per._name = '梅西' //报错,_name为私有属性,只能在类Person中访问和修改
// 如果我们想要修改 我们可以调用类中定义方法来提供外部可以修改,这样做更加安全
per.setName('梅西') //调用类Person中准备好的方法
console.log(per) //Person {_name: '梅西', _age: 32}
//如果我们想要读取也可以同理 如下
console.log(per.getName()) //梅西
/*
* protected演示
*/
class A {
protected num: number;
constructor(num: number) {
this.num = num;
}
}
class B extends A {
test() {
console.log(this.num);
}
}
const b = new B(123);
console.log(b.test()) // protected 受保护的属性,只能在当前类和当前类的子类中访问(修改)注意:不能通过实例对象直接调用
/*
* 可以直接将属性定义在构造函数中
*
* 下面两个构造方法效果是一样的!
*/
/*
class C{
name: string;
age: number
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}*/
class C {
// 可以直接将属性定义在构造函数中
constructor(public name: string, public age: number) {
}
}
})()
interface接口
/*
* 1、接口用来定义一个类结构,用来定义一个类中应该包含哪些属性和方法
* 2、同时接口也可以当成类型声明去使用
* 3、可以定义相同的接口,最后会合并在一起
* 4、接口里面的属性和方法不能有初始值
* 5、接口只考虑对象结构,而不考虑实际值
* 6、在接口中定义方法都是抽象方法,也就意味着需要重写
*/
interface myinterface {
name:string,
age:number
}
interface myinterface{
gender:string
sayHello():void
}
/*
定义类时,可以使类去实现一个接口
实现接口就是使类满足接口的要求
*/
class myClass implements myinterface{
constructor(public name:string, public age:number,public gender:string){
this.name = name
this.age = age
this.gender = gender
}
sayHello() {
console.log('你好呀~')
}
}
const myclass = new myClass('梅老板',37,'男')
console.log(myclass) //myClass {name: '梅老板', age: 37, gender: '男'}
console.log(myclass.sayHello()) //你好呀~
泛型
/*
泛型
使用场景:在定义函数或类时,如果遇到类型不明确就可以使用泛型
*/
function fn<T>(a:T):T{
return a
}
/* 可以直接调用具有泛型的函数 */
//1、不指定泛型,TS可以自动对类型进行推断
let results = fn(10) //TS 自动判断类型为number 然后T就为number
console.log(results) //10
//2、指定泛型
let results2 = fn<string>('hello')
console.log(results2) //hello
// 泛型可以指定多个
function fn2<T,K>(b:T,c:K):T{
return b
}
//多个 泛型 使用
let results3 = fn2<string,number>('hello',123)
console.log(results3) //hello
//泛型限制范围
interface inter{
lenght:number
}
// T extends Inter 表示泛型T必须时Inter实现类(子类)
function fn3<T extends inter>(a:T):number{
return a.lenght
}
//使用
console.log(fn3({lenght:10})) //10
/*类中使用泛型 */
class MyClass<T> {
name: T;
constructor(name: T) {
this.name = name;
}
}
const mc = new MyClass<string>('孙悟空')
console.log(mc) //MyClass {name: '孙悟空'}