【TS基础】个人学习记录4-类的定义、继承、修饰符、静态、只读、多态、抽象

类的声明

写法和es6一样

class Person{
    // 这里要声明有那些属性
	name:string // 前面省略了public
	age: number = 20 // 默认参数
	constructor(n:string){   // 实例化后会触发的方法,n只是个形参,不一定要和name重名
		this.name = n
	} 
	run():void{
		console.log('run')
	}
}

let p = new Person('a') 
let p1: Person = new Person('b')

特别说明:初学者可能会有这样的疑问,为啥在类中开头定义了参数,constructor还要再定义一次呢?

class User {
	// 其实这样定义的是属性,其中如果不用constructor来获得属性值的来源,那么一定要手动去赋值其他或者给个默认参数
	username: string | undefined 
	password: string | undefined
}
let u = new User()
u.username = 'xiaoming'
u.password = '1234'

等同于

class User {
	username: string 
	password: string 
    constructor(username: string, password: string) { // constructor就是用参数给属性赋值
        this.username = username
        this.password = password
    }
}
let u = new User('xiaoming', '1234')

存取器

在类中怎么实现get和set(存取器

class Son {
  firstName: string;
  lastName: string = 'Stark';
  constructor(firstName: string) {
    this.firstName = firstName;
  }
}

class GrandSon extends Son {
  constructor(firstName: string) {
    super(firstName);
  }
  get myLastName() {
    return this.lastName;
  }
  set myLastName(name: string) {
    if (this.firstName === 'Tony') {
      this.lastName = name;
    } else {
      console.error('Unable to change myLastName');
    }
  }
}

const grandSon = new GrandSon('Tony');
console.log(grandSon.myLastName); // => 触发get函数,返回带有默认值的"Stark"
grandSon.myLastName = 'Rogers';  
console.log(grandSon.myLastName); // => 触发set函数,此时firstName ='Tony',所以可以走if里的逻辑,"Rogers"
const grandSon1 = new GrandSon('Tony1'); 
grandSon1.myLastName = 'Rogers'; // => 触发set函数,此时firstName !='Tony'所以"Unable to change myLastName"

继承

和es6一样的,用关键词extendssuper

class Person {
	name: string
	constructor(name: string) {
		this.name = name
	}
}

class Son extends Person {
	constructor(name: string) { // ts规定,当使用了constructor必须调用super
		super(name) // 调用父类的 constructor(name)
	}
	run() {
		return super.work() // 可以直接调用父类的work方法
	}
}

let s = new Son("son")

注意:如果继承的方法与子类新增的同名,那么子类在实例化调用的时候会先去找子类身上的,没有再去找父类定义的。

tips:派生类通常被称作子类,基类也被称作超类(或者父类)。


修饰符

  • public:表示公有,在父类定义函数中和外,以及子类都能直接以任何形式访问。
  • protected:表示保护,在父类定义函数中和子类可以访问,但类定义函数外不能以获取属性形式访问。
  • private:表示私有,只有在父类定义函数中访问,子类函数内部无法访问(但可通过外面调用继承的父类方法去访问)。

不加修饰符默认为public。

class Person{
	protected name:string 
	private age:number
	constructor(n:string, a:number){   // 实例化后会触发的方法
		this.name = n
        this.age = a
	} 
	run():void{
		console.log(this.name + 'run')
	}
    tell():void{
        console.log('我'+this.age+'岁') // 私有只能在当前类中使用
    }
}
class Son extends Person{
	constructor(name: string, age:number) {
		super(name, age)
	} 
    //tell():void{
    //    console.log(this.age)  // 如果这里这样写就会报错不能使用私有类型
    //}
}
let p = new Person('p', 18)
// console.log(p.name) 外部访问保护类型报错
// console.log(p.age) 外部访问私有类型报错
p.run()
p.tell() // 从内部访问私有类型可以访问

let s = new Son('a', 6)
s.run() // 可以运行,保护类型子类可以访问
s.tell() // 从内部访问私有类型可以访问

补充:如果父类连constructor都设置privateprotected,那子类就不允许继承里面的东西。

tips:个人觉得可以这样子记。爸爸标记了public的东西A,意思是儿子在家里(class函数内)和家外面(class函数外),可以随便拿爸爸的东西A;爸爸标记了protected的东西B,意思是儿子在家里可以随便拿爸爸的东西B,但是在外面需要经过爸爸的同意(通过调用继承的父级方法)才能拿东西B;爸爸标记了private的东西C,意思是爸爸的私人物品,儿子只能在外面求爸爸要(通过调用继承的父级方法)才给。


静态属性与静态方法

静态属性:存在于类这个特殊的对象上,而不是类的实例上,所以我们可以直接通过类访问的属性。

静态方法:就是不在构造函数中赋予的方法(实例方法),而是实例化对象后,给对象后添加的方法。

怎么看第三方库哪些是静态方法,哪些是实例方法。例如JQ:

function $(el){
	return new Base(el)
}
function Base(el){
	this.el = 获取dom节点
	this.css = function(attr, value){  // 实例方法
		this.el.style.attr = value
	}
}
$.get = function(){  // 静态方法
	// get请求逻辑
}

// 所以会看到这么使用
$("#box").css('color', 'red')
$.get('url', function(){})

在TS中静态方法和静态属性是写在构造函数中的,用关键词static

class Person{
	public name:string // 前面省略了public
	static age = 12
	constructor(n:string){   // 实例化后会触发的方法
		this.name = n
	} 
	run():void{  // 实例方法
		console.log('run')
	}
	static work() {  // 静态方法
		console.log('不能划水')
	}
	static tell() {
		console.log(this.age)
	}
}
Person.work() // 可以不用实例化直接使用(在没有使用类中的非静态属性情况下)
Person.tell() // 调用了静态属性
let p = new Person('name')
p.work() // ;实例化后使用静态方法或属性直接报错

再来个简单例子,ts中的Math是一个内置的构造函数,你可以直接使用他的方法,例如Math.pow(),是因为他在构造函数内部声明的是静态方法。

引用:基于静态属性的特性,我们往往会把与类相关的常量、不依赖实例 this 上下文的属性和方法定义为静态属性,从而避免数据冗余,进而提升运行性能。


只读

用readonly修饰只读属性:

class Person{
  readonly name;
  // private readonly xxx 有其他修饰符要写在后面
  public constructor(name) {
    this.name = name;
  }
}
let p = new Person('a')
p.name = 'b' // 修改就报错

多态

可以理解为,父类定义一个方法不去实现,让继承的子类去实现,而且每个子类有不同的表现。

例子:

class Person {
	public: string;
	constructor(name: string) {
		this.name = name
	}
	run() {
		console.log(‘什么是多态’)
	}
}

class Son extends Person{
	constructor(name: string) {
		super(name)
	}
	run() {
		console.log(‘重写这个方法的具体内容’)
	}
}

有点方法重写的意思在里面。


抽象方法

先说什么是抽象类:提供其他类继承的基类,啥意思呢,主要用来定义继承标准,要求子类也必须服从这个标准。

abstract关键词定义抽象方法。

abstract class Person{
	name: string
	constructor(name: string){
		this.name = name
	}
	abstract run():any;  // 抽象方法只能放在抽象类中,如果类不声明abstract就会报错。抽象类中的抽象方法不包含具体实现。
}

// let p = new Person() 抽象类不能被实例化,会报错

class Son extends Person{
	constructor(name: string){
		super(name)
	} 
	run(){ // 抽象类方法必须!!在子类继承并且实现,否则报错
		xxx
	}
}

和多态很像,感觉抽象就是多态的强制版233 。


类的类型

类也可以作为一个变量的类型:

class A {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}

const a1: A = {}; // 报错
const a2: A = { name: 'a2' }; 

个人猜测vue3+ts里很多自带的变量类型很有可能就是自封的类。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值