今天我们来聊聊类类型
什么是类
类:描述了所创建的对象共同的属性和方法。
类:可以理解为模版,通过模板可以实例化对象,体现的是面向对象的编程思想。
类的目的:实例化对象,实现面向对象的编程思想
TypeScript中类的定义及使用
TypeScript 是面向对象的 JavaScript。
TypeScript 支持面向对象的所有特性,比如 类、接口等。
TypeScript 类定义方式如下:
1、声明/定义一个类
class class_name {
// 类作用域
//a、定义属性
//b、定义构造函数:为了将来实例化对象的时候,可以对属性的值进行初始化
//c、定义实例方法
}
2、实例化对象
const xx = new class_name()
再来举个案例吧
//1、定义/声明一个类
class Person {
//a、定义属性
name:string
age:number
sex:string
//b、定义构造函数:为了将来实例化对象的时候,可以对属性的值进行初始化
constructor(name:string="Amy",age:number=18,sex:string){//此写法是为了表示构造函数可以传递初始值
//更新对象中的属性数据
this.name = name//访问的是类的成员
this.age = age
this.sex = sex
}
//c、定义实例方法
say(str:string):string{
console.log(`你好,我是${this.name},我今年${this.age}了,我是${this.sex}孩子,`,str)
}
}
//2、实例化对象
const person = new Person("jack",55,"男")
person.say("你叫什么呢?")
是不是对于类的记忆又回来了呢?
TypeScript的类是基于JavaScript的类的面向对象的方式特性,并且编译后的 JavaScript 可以在所有主流浏览器和平台上运行,
TypeScript类的继承性
TypeScript 支持继承类,即我们可以在创建类的时候继承一个已存在的类,这个已存在的类称为父类,继承它的类称为子类。
类继承使用关键字 extends
,子类可以使用父类的构造函数(通过super(传递参数)
实现)和父类的实例方法(使用super.say()
实现),子类可以重写父类的方法
//继承:类与类之间的关系及继承后类与类之间的叫法,一旦发生了继承关系,就出现了父子类的关系
//a类继承了b类,那么a类叫子类,b叫基类
//子类:派生类
//基类:超类(父类)
//1、定义一个类,作为一个基类
class Person {
//a、定义属性
name:string
age:number
sex:string
//b、定义构造函数:为了将来实例化对象的时候,可以对属性的值进行初始化
constructor(name:string="Amy",age:number=18,sex:string){
//更新对象中的属性数据
this.name = name//访问的是类的成员
this.age = age
this.sex = sex
}
//c、定义实例方法
say(str:string):string{
console.log(`你好,我是${this.name},我今年${this.age}了,我是${this.sex}孩子,`,str)
}
}
//1.1、定义一个子类,继承自Person
class Student extends Person{
constructor(name:string,age:number,sex:string){
super(name,age,sex)//使用super调用父级构造函数
}
//可以调用父级的方法
say(){
console.log(“我是学生中的say方法”)
super.say("你是谁呢")//子类调用父类的实例方法用super关键字
}
}
//2、实例化父类实例对象
const person = new Person(“白菜”,18,“女”)
person.say("啦啦")
//2.1、实例化子类实例对象
const student = new Student(“萝卜”,88,“男”)
student.say()
TypeScript中类的多态
多态:父类型的引用指向了子类型的对象,不同类型的对象针对相同的方法,产生了不同的行为。
如果你足够熟悉javascript的话,对于多态可以只用了解上面的内容,如果有不太了解的地方,我们就用下面这个实例一起来看看吧
//多态:父类型的引用指向了子类型的对象,不同类型的对象针对相同的方法,产生了不同的行为
//1:定义一个父类:动物
class Animal {
//a、定义一个属性
name:string
//b、定义一个构造函数
constructor (name:string="动物"){
this.name = name
}
//定义一个实例方法
run(dis:number = 0){
console.log(`我是${name},我跑了${dis}米`,)
}
}
//1.1:狗,继承了父类
class Dog extends Animal{
constructor (name:string="小狗"){
//调用父类的构造函数,实现子类中的属性的操作
super(name)
}
//实例方法:重写父类中的实例方法
run(dis:number = 10){
console.log(`我是${name},我跑了${dis}米`,)
}
}
//1.1:定义第二个子类:猪,继承了父类
class Pig extends Animal{
constructor (name:string="小猪"){
//调用父类的构造函数,实现子类中的属性的操作
super(name)
}
//实例方法:重写父类中的实例方法
run(dis:number = 200){
console.log(`我是${this.name},我跑了${dis}米`,)
}
}
//2、实例化父类对象
const Ani :Animal = new Animal("动物")
Ani.run()
//2.1:实例化子类dog对象
const dog :Dog= new Dog("小黄")
dog.run()
//2.2:实例化子类pig对象
const pig:Pig= new Pig("八戒")
pig.run()
//3.1父类和子类的关系:父子关系,此时,父类类型创建了子类的对象
const dog1:Animal= new Dog("发财")
//不同类型的对象针对相同的方法,产生了不同的行为
dog1.run()
const pig1:Animal= new Pig("猪咪")
pig1.run()
//3.1不同类型的对象针对相同的方法,产生了不同的行为
function showrun (Ani:Animal){
Ani.run()
}
showrun(dog1)
showrun(pig1)
TypeScript中类的修饰符
修饰符:类中成员的修饰符描述类中的成员(属性、构造函数、方法)的可访问性
- 公共:
public
,类中成员默认的修饰符,代表任何位置都可访问类中的成员 - 私有:
private
,类中成员的私有修饰符,类中的成员使用private,外部成员无法访问成员数据。同时子类中也是无法访问该成员数据的 - 受保护的:
protected
,类中的成员受保护修饰符,类中成员使用protected修饰时,外部无法访问这个成员数据,但是子类是可以访问这个成员数据的。
//1、定义一个类
class Person {
//a、定义一个属性
//public name:string //public修饰了这个name属性,此时任何位置都可访问类中的成员
private name:string //private修饰了这个属性,此时console.log(per.name)的外部访问会报错;此时子类student的super方法也会报错
//b、定义一个构造函数
constructor (name:string="动物"){
this.name = name
}
//定义一个实例方法
run(dis:number = 0){
console.log(`我是${this.name},我跑了${dis}米`,)
}
}
//1.1:狗,继承了父类
class student extends Person{
constructor (name:string){
//调用父类的构造函数,实现子类中的属性的操作
super(name)
}
//实例方法:重写父类中的实例方法
play(){
console.log()
}
}
//2、实例化对象
const per = new Person(“猪猪精”)
//类的外面可以访问类的属性成员
console.log(per.name)
per.run()
TypeScript中类的readonly修饰符
readonly修饰符
:只读的,是一个关键字,对类中的属性成员进行修饰,修饰后,该属性成员就不能在外部被随意修改了
1、readonly修饰类中的成员属性
让我们先来看一个案例,在对ts的readonly修饰符进行总结吧
//1、定义一个类
class Person {
//属性
readonly name:string
//构造函数
constructor(name:string){
//更新对象中的属性数据
this.name= name //不报错
}
say(){
console.log(`我是${this.name}`)
this.name = "黑柴" **报错:**类中的普通方法中,也是不能够对readonly修饰符修饰的成员属性值进行修改
}
}
//2、实例化一个对象
const person:Person = new Person("欻欻")
console.log(person)
console.log(person.name)//欻欻
person.name = "黑柴" **报错**:添加readonly修饰符后报错:此时person的name属性是只读的,不能被其外部修改
//console.log(person.name)//黑柴
此时我们可以发现:
- 类的构造函数中,可以对只读属性成员的属性值进行修改:即
更新对象中的属性数据后this.name= name 不报错
- 类的构造函数中,如果没有任何参数,类中的属性成员已经使用readonly修饰,外部的成员也是不能够对这个属性值进行更改的
- 类中的普通方法中,也是不能够对readonly修饰符修饰的成员属性值进行修改 ,
say(){this.name = "黑柴" //报错:类中的普通方法中,也是不能够对readonly修饰符修饰的成员属性值进行修改 }
- 实例化对象后,外部不能够对readonly修饰符修饰的类的属性值进行修改
person.name = "黑柴" //添加readonly修饰符后报错:此时person的name属性是只读的,不能被其外部修改
2、readonly修饰类中构造函数的参数
我们再来看看readonly修饰类中构造函数的参数有什么样的特点吧
//1、定义一个类
class Person {
//构造函数
constructor(readonly name:string){
this.name= name //不报错且可以注释掉
}
}
//2、实例化一个对象
const person:Person = new Person("欻欻")
console.log(person)
console.log(person.name)//欻欻
person.name = "黑柴" //报错,外部无法修改类中的name属性成员值的
- //构造函数中的name参数:一旦使用readonly修饰符修饰,那么name参数可以叫做参数属性
constructor(readonly name:string){}
- 构造函数中的name参数,一旦使用readonly修饰符修饰,那么Person中就有了一个name的属性成员
- 构造函数中的name参数,一旦使用readonly修饰符修饰,外部无法修改类中的name属性成员值的
- 构造函数中的name参数,一旦使用rpublic修饰符修饰,Person中就有了一个公共的name的属性成员
TypeScript中类的存取器
TypeScript支持通过getters/setters来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问。
首先,我们从一个简单使用存取器的例子开始
- set :设置器:负责设置及修改数据
- get :读取器:负责读取数据,必须要有返回值
//需求:外部传入形式和名字数据,同时通过set/get控制姓名的数据,外部也可以进行修改和操作
//1、定义一个类
class Person {
//姓名的成员属性(外部可以访问也可以进行修改)
firstName:string
lastName:string
//构造器
constructor(firstName:string,lastName:string){
this.lastName = lastName
this.firstName = firstName
}
//set :设置器:负责设置及修改数据
set fullName(val){
let name = val.split("-")
this.firstName= name[0]
this.lastName= name [1]
}
//get :读取器:负责读取数据,必须要有返回值
get fullName(){
return this.firstName+"-"this.lastName
}
}
//2、实例化对象
const person = new Person("东方","不败")
console.log(person)
console.log(person.fullName)//可以获取到,称为获取该属性成员属性
person.fullName("诸葛-四郎")//可以进行设置,称为存取该属性成员数据
console.log(person.fullName)
TypeScript中类的静态成员
静态成员:在类中通过static修饰符修饰的属性或方法,称为类的静态属性及静态方法,也称之为静态成员。构造函数是不能通过static进行修饰
静态成员在使用的时候,是通过类名.静态方法()
的方式调用的
- 静态属性
- 静态方法
还是通过案例来查看
//1、定义一个类
class Person {
//静态属性
static name1:string
constructor( name1:string){
//this.name1= name1 //此时,this是实例对象,name1是静态属性,不能通过实例对象直接调用静态属性来使用
}
static say(){
console.log("你好")
}
}
//2、实例化一个对象
const person:Person = new Person("欻欻")
//通过实例对象调用的属性(实例属性)
//console.log(person.name1)//报错:此时,this是实例对象,name1是静态属性,不能通过实例对象直接调用静态属性来使用
//通过实例对象调用的方法(实例方法)
//person.say()
Person.say() //通过类.静态方法名的方式来调用类的静态方法
Person.name1 = "xinxin" //通过类名.静态属性的方法来访问类中成员的属性
- 使用 静态属性后,不能在构造函数中使用this来更改对象中的属性数据,因为this是实例对象,name1是静态属性,不能通过实例对象直接调用静态属性来使用
- 使用 静态方法后,不能通过实例方法来调用静态方法,而是需要使用
类.静态方法名
的方式来调用类的静态方法