1.类(class)
1.1介绍
要想面向对象,操作对象,首先便要拥有对象,那么下一个问题就是如何创建对象。要创建对象,必须要先定义类,所谓的类可以理解为对象的模型,程序中可以根据类创建指定类型的对象。
1.2定义
定义
class 类名 extends 类名 {
属性名: 类型;
constructor(参数: 类型){
this.属性名 = 参数;
}
方法名(){
....
}
}
属性
readonly表示只读属性
static 在属性前使用static关键字可以定义类属性(静态属性),直接使用类去访问
constructor 构造函数
extends 继承(通过继承可以将其他类中的属性和方法引入到当前类中)
abstract 抽象类
// abstract开头的类是抽象类 不能进行创建对象
// 抽象类只能用来进行继承
// 抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
public //公共属性可以在任意位置修改
private //私有属性只能在类的内部访问(修改),通过在类中添加方法使得私有属性可以被外部访问
protected //受保护的属性,只能在当前类和当前类的子类中访问(修改)
1.3使用
1.3.1基础
// 使用class关键字定义一个类
// 对象中包含 属性和方法
class Person {
// 定义实例属性,必须通过对象的实例去访问
name: string = 'zs'
age: number = 18
// 定义静态属性
static value: number = 20
// 定义只读的实例属性
readonly name1: string = 'ws'
// 定义只读的静态属性
static readonly value1: number = 20
// 定义实例方法
sayHello() {
console.log(123)
}
// 定义静态方法
static sayRed() {
console.log(234)
}
}
// 创建实例
const per = new Person()
console.log(per)
console.log(per.name)
per.name = 'ww'
console.log(per.name)
per.sayHello()
// 直接访问静态属性
console.log(Person.value)
Person.sayRed()
1.3.2构造函数
class Dog {
name: string
age: number
// constructor 被称为构造函数
// 构造函数会在对象创建时调用
constructor(name: string, age: number) {
// 在实例方法中,this表示当前的实例
// 可以通过this向创建的对象中添加属性
this.name = name
this.age = age
}
back() {
// 在方法中可以通过this来表示当前调用方法的对象
console.log(this.name)
}
}
const dog = new Dog('ss', 2)
const dog1 = new Dog('zz', 3)
const dog2 = new Dog('aa', 4)
const dog3 = new Dog('dd', 5)
console.log(dog)
console.log(dog1)
console.log(dog2)
console.log(dog3)
1.3.3继承
class AA {
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
sayholle() {
console.log('123')
}
}
// CC 继承了AA
// 使用继承后,子类将继承父类中所有的属性和方法
// 通过继承可以将多个类中共有的代码写在一个公共的类,避免编写重复代码
// 如果子类需要添加父类中没有的属性或方法可以直接加
// 子类中存在和父类相同的方法会覆盖父类中的方法(叫做方法的重写)
class CC extends AA {
value: string = '123'
re: number
constructor(name: string, age: number, re: number) {
// 在子类中写构造函数必须对父类的构造函数进行调用
super(name, age) //调用父类的构造函数
this.re = re
}
run() {
console.log(`${this.name}122`)
}
sayholl() {
// 在类的方法中supper就表示当前类的父类
super.sayholle()
// console.log(123)
}
}
class DD extends AA {
sayholle() {
console.log(123)
}
}
const cc = new CC('wc', 2, 3)
cc.run()
cc.sayholl()
console.log(cc)
const dd = new DD('mm', 2)
console.log(dd)
1.3.4 抽象类
// abstract开头的类是抽象类 不能进行创建对象
// 抽象类只能用来进行继承
abstract class AA {
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
sayholle() {
console.log('123')
}
// 创建抽象方法
// 抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
abstract say(): void
}
class CC extends AA {
say(): void {
console.log(123)
}
}
class DD extends AA {
say(): void {
console.log(234)
}
}
const cc = new CC('wc', 2)
console.log(cc)
const dd = new DD('mm', 2)
console.log(dd)
1.3.5属性封装
class Person {
public name: string
private age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
// 获取age属性
getAge() {
return this.age
}
// 设置age属性
setAge(value: number) {
// 可以进行条件判断
this.age = value
}
// ts中设置getter方法的方式
get _name() {
return this.name
}
set _name(value: string) {
this.name = value
}
}
const per = new Person('cc', 212)
per.setAge(2)
per._name = 'dd'
console.log(per.getAge())
console.log(per._name)
console.log(per.name)
1.3.5属性封装
class Person {
// public 公共属性可以在任意位置修改
// private 私有属性只能在类的内部访问(修改),通过在类中添加方法使得私有属性可以被外部访问
// protected 受保护的属性,只能在当前类和当前类的子类中访问(修改)
public name: string
private age: number
protected value1: number
constructor(name: string, age: number, value1: number) {
this.name = name
this.age = age
this.value1 = value1
}
// 获取age属性
getAge() {
return this.age
}
// 设置age属性
setAge(value: number) {
// 可以进行条件判断
this.age = value
}
// ts中设置getter方法的方式
get _name() {
return this.name
}
set _name(value: string) {
this.name = value
}
}
class aa extends Person {
text() {
console.log(this.value1)
}
}
const per = new Person('cc', 212, 123)
per.setAge(2)
per._name = 'dd'
console.log(per.getAge())
console.log(per._name)
console.log(per.name)
1.3.6简单写法
class DD1 {
constructor(public name: string, public age: number) {}
}
const dd1 = new DD1('123', 2)
console.log(dd1)
1.4接口
1.4.1介绍
接口的作用类似于抽象类,不同点在于接口中的所有方法和属性都是没有实值的,换句话说接口中的所有方法都是抽象方法。接口主要负责定义一个类的结构,接口可以去限制一个对象的接口,对象只有包含接口中定义的所有属性和方法时才能匹配接口。同时,可以让一个类去实现接口,实现接口时类中要保护接口中的所有属性。
1.4.2使用
// 接口用来定义一个类结构,用来定义一个类中包含哪些属性和方法,同时可以当成类型声明使用
// 接口可以在定义类的时候去限制类的结构
// 接口只能定义对象的结构,而不能赋值
interface cc {
name: string
age: number
say(): void
}
interface cc {
value: number
}
const bb: cc = {
name: '123',
age: 1,
value: 2,
say() {
console.log(123)
}
}
// 实现接口就是使类满足接口的要求
class ww implements cc {
name: string
age: number
value: number
constructor(name: string, age: number, value: number) {
this.name = name
this.age = age
this.value = value
}
say(): void {
throw new Error('Method not implemented.')
}
}
1.5泛型
1.5.1介绍
定义一个函数或类时,有些情况下无法确定其中要使用的具体类型(返回值、参数、属性的类型不能确定),此时泛型便能够发挥作用。
1.5.2使用
function fn<T>(a: T): T {
return a
}
// 可以直接调用具有泛型的函数
fn(10) //不指定泛型,Ts可以直接对类型进行推断
fn<string>('123') // 指定泛型
//可以同时指定多个泛型,泛型间使用逗号隔开
function fn2<T, K>(a: T, b: K): T {
return a
}
fn2<number, string>(1, '22')
//类中使用泛型
class CC1<T> {
name: T
constructor(name: T) {
this.name = name
}
}
let cc1 = new CC1<string>('cc')
console.log(cc1)
//可以对泛型的范围进行约束
//使用T extends MyInter表示泛型T必须是MyInter的子类
interface Inter {
length: number
}
function fn3<T extends Inter>(a: T): T {
console.log(a.length)
console.log(a)
return a
}
let aa = fn3('123')
let aa1 = fn3({ length: 1, name: '12' })