一. 认识类的使用:
![](https://img.haomeiwen.com/i19041386/1ea524a18f754d9f.png)
二. 类的定义
![](https://img.haomeiwen.com/i19041386/3706d1c270d22ec3.png)
// TS类的基本定义
class Person {
name: string
age: number
eating() {
console.log(this.name + "eating");
}
}
export {}
TS 在严格模式下要赋值
![](https://img.haomeiwen.com/i19041386/d3ba01e5eff3ff25.png)
三. 一 类的继承
![](https://img.haomeiwen.com/i19041386/561d2a5d75dc30e6.png)
class Person {
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
eating() {
console.log('Person eating~');
}
}
// 继承 学生 Student extends Person
class Student extends Person {
sno: number
constructor(name: string, age: number, sno: number) {
// super调用父类的构造器
super(name, age)
this.sno = sno
}
/**
* PS: 其实这个地方可以不写这个函数,直接去继承父类的eating函数,
* 但是需求是: 我只想在我自己的类中写自己的处理逻辑,不想去继承父类的,
* 这个时候就可以在自己类中重写一个eating方法,
*/
eating() {
console.log('Student eating~');
}
studying() {
console.log('studying');
}
}
// 学生:
const stu = new Student('huzhenchu', 18, 11);
console.log(stu.name);
console.log(stu.age);
console.log(stu.sno);
stu.eating() // 他的执行顺序是: 如果在自己的类中找不到eating方法就会去父类中去找,
stu.studying() // 他的执行顺序是: 如果在自己的类中找不到studying方法就会去父类中去找,
export { }
三.二.需求:
需求:如果你还想在执行自己类中的方法的时候,还想执行父类中的eating方法 那该咋办呢?
class Person {
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
eating() {
console.log("我是Person 中的 eating");
}
}
// 学生继承Person中的属性和方法
class Student extends Person {
sno: number
constructor(name: string, age: number, sno: number) {
super(name, age);// 这个super是调用父类的构造器
this.sno = sno
}
studying() {
console.log("studying");
}
// 如果子类不满意父类 Person中的eating方法的话,子类可以在自己的class 中重写eating方法的
eating() {
// 需求:如果你还想在执行自己类中的方法的时候,还想执行父类中的eating方法 那该咋办呢?
super.eating()
console.log("我是 student中的 eating方法");
}
}
const stu = new Student("why", 18, 1111)
console.log(stu.name);
console.log(stu.age);
console.log(stu.sno);
stu.eating()
export { }
实际截图
![](https://img.haomeiwen.com/i19041386/cae42352e1c90f60.png)
三.三 类的多态
animal.action // 他的执行顺序是: 如果在自己的类中找不到action方法就会去父类中去找,
animal.action // 他的执行顺序是: 如果在自己的类中找不到action方法就会去父类中去找,
class Animal {
action() {
console.log("animal running");
}
}
class Dog extends Animal {
action() {
console.log("dog running !!!");
}
}
class Fish extends Animal {
action() {
console.log("Fish swimming!!!");
}
}
function makeActions(animals: Animal[]) {
animals.forEach(animal => {
animal.action(); // 他的执行顺序是: 如果在自己的类中找不到action方法就会去父类中去找,所以当前的action指向的当前各自类中的action方法
})
}
makeActions([new Dog(), new Fish()]);
export {}
实际截图
![](https://img.haomeiwen.com/i19041386/e019b3ccc5d31014.png)
四.类的成员修饰符
![](https://img.haomeiwen.com/i19041386/d0fad446206207b3.png)
四.一 public修饰符
/**
* 1. public 修饰符 public 修饰的是在任何地方可见、公有的属性或方法,默认编写的属性就是public的;
*
* 他可以在在类的内部访问,也可以在外面访问,取值和赋值都是可以的
* **/
class Person {
public name: string = ""
}
const p = new Person()
console.log(p.name);
image.png
四.二 类的成员修饰符-private修饰符的使用
/**
* 2. private 修饰的是仅在同一类中可见、私有的属性或方法;
*
* 他只能在类的内部访问,在外面访问直接报错,取值和赋值都是不可以的
* **/
class Person1 {
private name: string = "";
// 如果你想获取Person1中的name的值得话 只能定义一个函数 然后让这个getName函数 在内部访问 这个name,最后在外部使用p1.getName()去调用获取到这个name值
getName() {
return this.name
}
// 如果你想设置Person1中的name的值得话 只能定义一个函数 然后让这个setName函数 在内部访问 这个name,最后在外部使用p1.setName()去调用获取到这个name值
setName() {
return this.name = "楚楚胡"
}
}
const p1 = new Person1()
// console.log(p1.name); // 所以这里是访问不到的,直接报错,
console.log(p1.getName());
console.log(p1.setName());
export {}
实际截图
![](https://img.haomeiwen.com/i19041386/0f20cb2892193461.png)
四.三 07_类的成员修饰符-protected修饰符的使用
// 3. protected 修饰的是仅在类自身和子类中可见、受保护的属性或方法;也就是说 在自己类的内部和子类继承中访问
class Person {
// protected 修饰的是仅在类自身及子类中可见、受保护的属性或方法;
protected name: string = "123"
}
class Student extends Person {
getName() {
return this.name
}
}
const stu = new Student()
// console.log(stu.name); // 所以这里是访问不到的,直接报错,因为他 修饰的是仅在类自身及子类中可见
console.log(stu.getName());
export {}
实际截图
![](https://img.haomeiwen.com/i19041386/ffbbc18616cf42dd.png)
五. 只读属性readonly
![](https://img.haomeiwen.com/i19041386/8a0637a2b597cbd4.png)
class Person {
// 1. 只读属性是在constcurtor中赋值的,赋值以后就不可以修改了
// 2. 属性本身不能进行修改,但是如果他是对象类型, 对象的属性是可以修改的
readonly name:string
readonly friend?:Person
age?:number
constructor(name:string,friend?:Person){
this.name = name
this.friend = friend
}
}
const p = new Person ("huzhenchu",new Person("Kobe"))
console.log(p.name)
console.log(p.friend)
// p.friend = new Person("Jamess"); // 只读属性 这里就不可以再做修改了
if(p.friend) {
p.friend.age = 30
}
实际截图
![](https://img.haomeiwen.com/i19041386/ff24ef56ed8f1427.png)
六. getters/setters
![](https://img.haomeiwen.com/i19041386/feae532550df0381.png)
class Person {
private _name: string // 私有属性
constructor(name: string) {
this._name = name
}
// 访问器setter/getters
set name(newName) {
this._name = newName
}
// getter
get name() {
return this._name
}
}
const p = new Person("huzhenchu");
// 设置属性
p.name = "huzhenchu";
// 获取
console.log(p.name);
实际截图
![](https://img.haomeiwen.com/i19041386/972f36dca20349a9.png)
七.静态成员
![](https://img.haomeiwen.com/i19041386/bd5138254a334d6b.png)
// class Person {
// name:string =""
// age:number = 12
// }
// const p = new Person()
// p.name = "123"
/**
* 1. static 类的静态属性
* 上面的那这种是要new Person
* 但是 我们使用 static 属性以后 可以直接去访问类里面的属性
*
*
* **/
class Student {
static time: string = "20:00"
static attendClass() {
console.log("去学习~");
}
}
console.log(Student.time);
Student.attendClass()
实际截图
![](https://img.haomeiwen.com/i19041386/1f223dabebb21726.png)
八.抽象类abstract
![](https://img.haomeiwen.com/i19041386/a33608ef367e9a93.png)
// 1. 原始写法
function makeArea(shape: any) {
return shape.getArea()
}
// 计算矩形的面积
class Reactangle {
private width: number
private height: number
constructor(width: number, height: number) {
this.width = width
this.height = height
}
getArea() {
return this.width * this.height
}
}
const rectangle = new Reactangle(20, 30)
console.log(rectangle); // { width: 20, height: 30 }
console.log(makeArea(rectangle)); // 600
// 计算圆形的面积
class Circle {
private r: number
constructor(r: number) {
this.r = r
}
getArea() {
return this.r * this.r * 3.14
}
}
const circle = new Circle(10);
console.log(makeArea(circle)); // 314
/*********************************************/
// 2. 抽象类abstract
function makeArea(shape: Shape) {
return shape.getArea()
}
abstract class Shape {
// 抽象类abstract
abstract getArea()
}
// 计算矩形的面积
class Reactangle extends Shape{
private width: number
private height: number
constructor(width: number, height: number) {
super()
this.width = width
this.height = height
}
getArea() {
return this.width * this.height
}
}
const rectangle = new Reactangle(20, 30)
console.log(rectangle); // { width: 20, height: 30 }
console.log(makeArea(rectangle)); // 600
// 计算圆形的面积
class Circle extends Shape {
private r: number
constructor(r: number) {
super()
this.r = r
}
getArea() {
return this.r * this.r * 3.14
}
}
const circle = new Circle(10);
console.log(makeArea(circle)); // 314
实际截图
![](https://img.haomeiwen.com/i19041386/769521ac7ba68256.png)
九.抽象类演练
![](https://img.haomeiwen.com/i19041386/77b8277048a9818b.png)
十. 类的类型
![](https://img.haomeiwen.com/i19041386/37ebae199bc2455f.png)
class Person {
name: string = "123"
eating(){}
}
const p = new Person();
// 这种就叫做类的类型
const p1: Person = {
name: "chuchuhu",
eating(){
console.log("ahahah");
}
}
// 实际用途
function printPerson(p:Person) {
console.log(p.name);
}
printPerson({name:"Kobe",eating:function(){}})
export {}
十一.接口的声明
![](https://img.haomeiwen.com/i19041386/9574f748a8489b62.png)
// 1. 通过类型(type)别名 来声明对象类型
type InfoType = { name: string, age: number }
const info: InfoType = {
name: "why",
age: 18
}
// 2.另外一种方式声明对象类型: 接口interface
interface InfoType {
name: string
age: number
}
const info: InfoType = {
name: "why",
age: 18
}
十二.可选属性
![](https://img.haomeiwen.com/i19041386/243bf816e7785359.png)
// 2.1 使用 interface定义的类型 --- 可选类型
interface InfoType1 {
name?:string
age?:number
}
const info1:InfoType1 = {
name:'chuchuhu', // 这些可写可不写
age:28 //这些可写可不写
}
十三. 只读属性
![](https://img.haomeiwen.com/i19041386/065ef07c5a87280b.png)
十四. 索引类型
![](https://img.haomeiwen.com/i19041386/860f12b09278412a.png)
/**
* 需求: 放到这个对象中的所有的 key 都时数字类型的,value都是字符串类型的
*
*
*
* **/
// 通过interface 来定索引类型
interface IndexLanguge {
[index: number]: string
}
const frontLanguage: IndexLanguge = {
0: 'HTML',
1: "CSS",
2: "JavaScript",
3: "Vue",
aaa: "1111" // 这里会直接报错,因为这个地方定义的 key 不是数字类型, 所以会报错,必须严格按照interface定义的数据来
}
/**
* Desc: 放到这个对象中的所有的 key 都是字符串类型的,value是number类型的
*
* **/
interface IlanguageYear {
[name: string]: number
}
const languageYear:IlanguageYear = {
"C": 1972,
"Jave": 1995,
"JavaScript": 1996,
"TypeScript": 2014
}
实际截图
![](https://img.haomeiwen.com/i19041386/75f4c90f982b3f98.png)
十五. 函数类型
![](https://img.haomeiwen.com/i19041386/3693a90cc7686d89.png)
// 1. 使用type定义类型
type CalFn = (n1: number, n2: number) => number
function calc(num1: number, num2: number, calcFn: CalFn) {
return calcFn(num1, num2)
}
const add: CalFn = (num1, num2) => {
return num1 + num2
}
console.log(calc(20, 30, add)); // 50
实际截图
![](https://img.haomeiwen.com/i19041386/f091beac5f0e6215.png)
十六. 接口继承
![](https://img.haomeiwen.com/i19041386/8d60dabbfa3623c1.png)
interface ISwim {
swimming: () => void
}
interface IFly {
flying: () => void
}
interface IAction extends ISwim, IFly {
}
const action: IAction = {
swimming() {
},
flying() {
}
}
十七. 接口的实现
![](https://img.haomeiwen.com/i19041386/969aefb85f447c35.png)
interface ISwim {
swimming: () => void
}
interface IEat {
eating: () => void
}
// 类实现接口
class Animal {
}
// 继承: 只能实现单继承
// 实现: 实现接口, 类可以实现多个接口
class Fish extends Animal implements ISwim, IEat {
swimming() {
console.log("Fish Swmming")
}
eating() {
console.log("Fish Eating")
}
}
class Person implements ISwim {
swimming() {
console.log("Person Swimming")
}
}
// 编写一些公共的API: 面向接口编程
function swimAction(swimable: ISwim) {
swimable.swimming()
}
// 1.所有实现了接口的类对应的对象, 都是可以传入
swimAction(new Fish())
swimAction(new Person())
swimAction({swimming: function() {}})
十八. 交叉类型
![](https://img.haomeiwen.com/i19041386/01545be8ce2fd664.png)
// 一种组合类型的方式: 联合类型
type WhyType = number | string
type Direction = "left" | "right" | "center"
// 另一种组件类型的方式: 交叉类型
type WType = number & string
interface ISwim {
swimming: () => void
}
interface IFly {
flying: () => void
}
type MyType1 = ISwim | IFly
type MyType2 = ISwim & IFly
const obj1: MyType1 = {
flying() {
}
}
const obj2: MyType2 = {
swimming() {
},
flying() {
}
}
export {}
十九. 交叉类型的应用
![](https://img.haomeiwen.com/i19041386/d4a8a1f041a6c93a.png)
二十. interface和type区别
![](https://img.haomeiwen.com/i19041386/43f47386745f30fa.png)
/**
* 1. interface和type区别:
* -- interface 可以重复的对某个接口来定义属性和方法;
* -- 如果名字相同的话,相当于是直接给合并了
* **/
interface IFoo {
name: string
}
interface IFoo {
age: number
}
// 如果名字相同的话,相当于是直接给合并了
interface IFoo {
name: string
age: number
}
const foo: IFoo = {
age: 19,
name: "why"
}
/**
* 2. interface和type区别:
* -- 而type定义的是别名,别名是不能重复的;
* -- 重复定义的话 直接会报错
*
* **/
type IBar = {
name: string
}
type IBar = {
age: number
}
export {}
实际截图
![](https://img.haomeiwen.com/i19041386/211d127b87476191.png)
二十一.字面量赋值
![](https://img.haomeiwen.com/i19041386/e5bcf53b2d531e1a.png)
interface IPerson {
name: string
age: number
height: number
}
// 需求: 上面定义好了 类型,但是我想在下面这个对象中多增加一个 address字段, 此时是会直接报错的
// const p: IPerson = {
// name: "hzc",
// age: 18,
// height: 1.88
// }
// 正确写法
const info = {
name: "hzc",
age: 18,
height: 1.88,
address: "武汉市"
}
const p: IPerson = info
function printInfo(info:IPerson) {}
printInfo(p)
网友评论