类的基本用例
// 类:可以理解为模板,通过模板可以实例化对象
// 面向对象的编程思想
(() => {
// ts中类定义及使用
class Person {
// 定义属性
name: string
age: number
gender: string
constructor(name: string = '张三', age: number = 13, gender: string = '女') {
// 更改对象中的属性数据
this.name = name
this.age = age
this.gender = gender
}
// 定义实例方法
sayHi(str: string) {
console.log(`大家好,我是${this.name},今年已经${this.age}岁了,是个${this.gender}孩子。`, str);
}
}
// ts中使用类,实例化对象,可以直接进行初始化操作
const person = new Person('11', 15, '男')
person.sayHi('111');
})()
类的继承
// 继承:类与类直接的关系
// 继承后类与类之间的叫法:
// A类继承了B这个类,那么此刻A类叫子类,B类叫基类
// 子类 --> 派生类
// 父类 --> 超类(父类)
// 一旦发生继承就出现了父子类的关系
(() => {
// 定义一个类
class Person {
// 定义属性
name: string // 名字
age: number
gender: string
// 定义构造函数
constructor(name: string = '小明', age: number = 18, gender: string = '男') {
this.name = name
this.age = age
this.gender = gender
}
// 定义实例方法
sayHi(str: string) {
console.log(`我是${this.name},${str}`);
}
}
// 定义一个类,继承自Person
class Student extends Person {
constructor(name: string, age: number, gender: string) {
// 调用的是父类中的构造函数,使用的是super
super(name, age, gender)
}
// 可以调用父类中的方法
sayHi() {
console.log('我是学生中的sayHi方法');
super.sayHi('haha')
}
}
// 实例化Person
const person = new Person('大明明', 89, '男');
person.sayHi('222')
// 实例化Student
const stu = new Student('小甜甜', 16, '女')
stu.sayHi()
// 总结:类和类之间如果要有继承关系,需要使用extends关键字
// 子类可以调用父类中的关键字,但是super关键字(包括调用父类中的实例方法,也可以使用super)
// 子类中可以重写父类中的方法
})()
多态
// 多态:父类型的引用指向子类型的对象,不用类型的对象针对不同的方法,产生了不同的行为
(() => {
// 定义一个父类
class Animal {
// 定义一个属性
name: string
// 定义一个构造函数
constructor(name: string) {
this.name = name
}
// 实例方法
run(distance: number = 0) {
console.log(`跑了${distance}这么远的距离`, this.name);
}
}
// 定义一个子类
class Dogs extends Animal {
// 构造函数
constructor(name: string) {
// 调用父类的构造函数实现了类中属性的初始化操作
super(name)
}
// 实例方法,重写父类中的实例方法
run(distance: number = 5) {
console.log(`跑了${distance}这么远的距离`, this.name);
}
}
// 定义一个子类
class Pig extends Animal {
// 构造函数
constructor(name: string) {
// 调用父类的构造函数实现了类中属性的初始化操作
super(name)
}
// 实例方法,重写父类中的实例方法
run(distance: number = 10) {
console.log(`跑了${distance}这么远的距离`, this.name);
}
}
// 实例化父类对象
const ani: Animal = new Animal('动物')
ani.run()
// 实例化子类对象
const dog: Dogs = new Dogs('大黄')
dog.run()
// 实例化子类对象
const pig: Pig = new Dogs('八戒')
pig.run()
// 父类和子类的关系:父子关系,此时,父类类型创建子类的对象
// 父类型的引用指向子类型的对象
const dog1: Animal = new Dogs('小黄')
dog1.run()
const pig1: Animal = new Pig('小猪')
pig1.run()
function showRun(ani: Animal) {
ani.run()
}
showRun(dog1)
showRun(pig1)
})()
公共,私有与受保护的修饰符
默认为 public
在上面的例子里,我们可以自由的访问程序里定义的成员。 如果你对其它语言中的类比较了解,就会注意到我们在之前的代码里并没有使用 public
来做修饰;例如,C# 要求必须明确地使用 public
指定成员是可见的。 在 TypeScript 里,成员都默认为 public
。
你也可以明确的将一个成员标记成 public
。 我们可以用下面的方式来重写上面的 Animal
类:
private
当成员被标记成 private
时,它就不能在声明它的类的外部访问。
protected
protected
修饰符与 private
修饰符的行为很相似,但有一点不同,protected
成员在派生类中仍然可以访问。例如:
// 修饰符(类中的成员装饰符):主要是描述类中的成员(属性,构造函数,方法)的可访属性
// 类中的成员都有自己默认的访问修饰符 public
// public 修饰符,类中的成员默认的修饰符,代表的是公共的,任何位置都可以访问类中的成员
// private修饰符,其中类的成员如果使用private来修饰,那么外部无法访问这个成员数据的,当然子类中也是无法访问成员数据的
// protected 修饰符 外部是无法访问的,在子类内可以访问该成员
(() => {
// 定义一个类
class Person {
// 属性 public 修饰了属性成员
// public name: string
// 属性 private 修饰属性成员
// private name: string
// 属性 protected 修饰属性成员
protected name: string
public constructor(name: string) {
// 更新属性
this.name = name;
}
// 方法
public eat() {
console.log('123');
}
}
// 再次定义一个子类
class Student extends Person {
constructor(name: string) {
super(name)
}
play() {
console.log('567', this.name);
}
}
// 实例化对象
const per = new Person('456')
// 在类的外部可以访问类的属性
// console.log(per.name);
per.eat()
const stu = new Student('12');
stu.play();
// console.log(stu.name);
})()
readonly
// readonly修饰符:首先是一个关键字,对类中的属性成员进行修饰,修饰后,该属性成员就不能在外部随意修改
// 构造函数中可以对只读的属性成员的数据进行修改
// 构造函数中没有任何的参数,类中的属性成员此时已经使用readonly进行修饰,那么外部是不能对这个属性值进行修改的
// 构造函数的参数可以使用readonly进行修饰,一旦修饰了,那么该类中就有了这个只读的属性,外部可以访问,但是不能修改
// 构造函数的参数可以使用public及pricvate和protected,无论是哪个进行修饰,该类中会自动添加一个属性成员
(() => {
// readonly 修饰类中的成员属性
// 定义一个类型
// class Person {
// readonly name: string = '100' // 初始值
// // 构造函数
// constructor(name: string) {
// this.name = name
// }
// sayHi() {
// console.log('123', this.name);
// // 类中的普通方法中也是不能修改readonly修饰成员属性值
// // this.name = '23';
// }
// }
// // 实例化对象
// const person: Person = new Person('56');
// console.log(person);
// console.log(person.name);
// // 在外部无法修改内部的只读属性
// // person.name = '123565';
// console.log(person.name);
// readonly 修饰类中的构造函数的参数(参数属性)
class Person {
// 构造函数中的name参数,一旦使用readonly进行修饰后,那么该name参数可以叫做参数属性
// Person中就有了一个name属性
// 外部无法修改类中的name属性成员值
// constructor(readonly name: string) {
// // this.name = name
// }
// 构造函数中的name属性,一旦使用public进行修改后,那么Person类中就有一个公共的name成员属性成员
// 同时这里也可以替换为private和protected属性
constructor(public name: string) {
// this.name = name
}
}
// 实例化对象
const person: Person = new Person('56');
console.log(person);
console.log(person.name);
// 在外部无法修改内部的只读属性
// person.name = '123565';
console.log(person.name);
})()
存取器
// 存取器:让我们可以有效的控制对 对象中的成员访问,通过getter和setter来进行操作
(() => {
// 外部可以传入姓氏和名字数据,同时使用set和get控制姓名数据,外部也可以进行修改操作
class Person {
firstName: string // 姓氏
lastName: string // 名字
constructor(firstName: string, lastName: string) {
this.firstName = firstName;
this.lastName = lastName;
}
// 姓氏的成员属性(外部可以访问,也可以修改)
// 读取器--负责读取数据
get fullName() {
return this.firstName + "_" + this.lastName
}
// 设置值--负责设置数据(修改)
set fullName(val) {
// 姓名--把姓氏和名字获取到重新赋值给firstName和lastName
let names = val.split("_");
this.firstName = names[0];
this.lastName = names[names.length - 1];
}
}
// 实例化对象
const person: Person = new Person("东方", "不败")
console.log(person.fullName) // 名字再获取中的时候会调用get
person.fullName = "诸葛_孔明" // 在设置数据的时候会触发set
console.log(person.fullName)
})()
静态属性
// 静态成员:在类中通过static修饰的属性或者方法,那么就是静态的属性或者静态的方法,也成为静态成员
// 静态成员在使用的时候是通过类名的这种 语法来调用的
(() => {
// 定义一个类
class Person {
// 类中默认有一个内置的name属性,在设置属性name时会出现错误
static name1: string = '123'
// 构造函数是不能通过static进行修饰的
constructor() {
// 此时this是实例对象,name1是静态属性,不同通过实例对象直接调用静态属性来使用
// this.name1 = name
}
// 静态方法
static sayHi() {
console.log('123456');
}
}
// 实例化对象
// const person: Person = new Person()
// 通过实例对象调用的属性(实例属性)
// console.log(person.name);
// 通过实例对象调用的方法(实例方法)
// person.sayHi()
// 通过类名.静态属性的方式来访问该成员数据
console.log(Person.name1);
// 通过类名.静态属性的方式来设置该成员数据
Person.name1 = '45'
console.log(Person.name1);
// 通过类名.静态属性的方式来调用内部的静态方法
Person.sayHi()
})()
抽象类
// 抽象类:包含抽象方法(抽象方法一般没有任何的具体内容实现),也是可以包含实例方法,抽象类是不能被实例化,为了让子类进行实例化及实现内部的抽象方法
// 抽象类的目的或作用都是为了子类服务
(() => {
// 定义一个抽象类
abstract class Animal {
// abstract name: string // 没有必要有一个抽象属性让子类去实现
// 抽象方法
abstract eat()
// 抽象方法不能有具体实现,例如:
// abstract eat(){
// console.log('123');
// }
// 实例方法
sayHi() {
console.log('你好');
}
}
// 定义一个子类(派生类)Dog
class Dog extends Animal {
name: string = 'dog'
// 重新的实现抽象类的方法,此时这个方法就是当前的Dog类的实例方法
eat() {
console.log('eat..');
}
}
// 实例化Dog对象
const dog: Dog = new Dog()
dog.eat()
// 调用的是抽象类中的实例方法
dog.sayHi()
console.log(dog.name);
// 不能实例化抽象类的对象
// const ani: Animal = new Animal()
})()