IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> typeScript(七)抽象类、类与接口、类与对象类型 -> 正文阅读

[JavaScript知识库]typeScript(七)抽象类、类与接口、类与对象类型

抽象类

  • 一个基类(父类)的一些方法无法确定具体的行为,而是由继承的子类去实现。
  • 比如组件化的 React:
class MyComponent extends Component { 
	constructor(props) { 
		super(props); 
		this.state = {} 
	}
	render() { 
		//... 
	} 
}
  • 根据上面代码,我们可以大致设计如下类结构
    • 每个组件都一个 props 属性,可以通过构造函数进行初始化,由父级定义
    • 每个组件都一个 state 属性,由父级定义
    • 每个组件都必须有一个 render 的方法
class Component<T1, T2> { 
	public state: T2; 
	constructor(public props: T1) { 
		// ... 
	}
	render(): string {
		// ...不知道做点啥才好,但是为了避免子类没有 render 方法而导致组件解析错误,
		// 父类就用一个默认的render 去处理可能会出现的错误 
	} 
}
interface IMyComponentProps { 
	title: string; 
}
interface IMyComponentState { 
	val: number; 
}
class MyComponent extends Component<IMyComponentProps, IMyComponentState> { 						
	constructor(props: IMyComponentProps) { 
		super(props); 
		this.state = { val: 1 } 
	}
	render() { 
		this.props.title; 
		this.state.val;
		return `<div>组件</div>`; 
	} 
}
  • 上面的代码虽然从功能上讲没什么太大问题,但是父类的 render 有点尴尬,更应该从代码层面上去约束子类必须得有 render 方法,否则编码就不能通过

abstract 关键字

  • 如果一个方法没有具体的实现方法,则可以通过 abstract 关键字进行修饰
abstract class Component<T1, T2> { 
	public state: T2; 
	constructor(public props: T1) 
	{ 
	
	}
	public abstract render(): string; 
}
  • 使用抽象类有一个好处:
    • 约定了所有继承子类的所必须实现的方法,使类的设计更加的规范

使用注意事项:
1、abstract 修饰的方法不能有方法体
2、如果一个类有抽象方法,那么该类也必须为抽象的
3、如果一个类是抽象的,那么就不能使用 new 进行实例化(因为抽象类表名该类有未实现的方法,所以不允许实例化)
4、如果一个子类继承了一个抽象类,那么该子类就必须实现抽象类中的所有抽象方法,否则该类还得声明为抽象的

类与接口

  • 通过接口,可以为对象定义一种结构和契约。我还可以把接口与类进行结合,通过接口,让类去强制符合某种契约,从某个方面来说,当一个抽象类中只有抽象的时候,它就与接口没有太大区别了,这个时候,更推荐通过接口的方式来定义契约。
    • 抽象类编译后还是会产生实体代码,而接口不会
    • TypeScript 只支持单继承,即一个子类只能有一个父类,但是一个类可以实现过个接口
    • 接口不能有实现,抽象类可以

implements

  • 在一个类中使用接口并不是使用 extends 关键字,而是 implements
    • 与接口类似,如果一个类 implements 了一个接口,那么就必须实现该接口中定义的契约
    • 多个接口使用 , 分隔
    • implements 与 extends 可同时存在
interface ILog { 
	getInfo(): string; 
}
class MyComponent extends Component<IMyComponentProps, IMyComponentState> implements ILog { 
	constructor(props: IMyComponentProps) { 
		super(props); 
		this.state = { val: 1 } 
	}
	render() { 
		this.props.title; 
		this.state.val; 
		return `<div>组件</div>`; 
	}
	getInfo() { 
		return `组件:MyComponent,props:${this.props},state:${this.state}`; 
	} 
}
  • 实现多个接口
interface ILog { 
	getInfo(): string;
}
interface IStorage { 
	save(data: string): void; 
}
class MyComponent extends Component<IMyComponentProps, IMyComponentState> implements ILog, IStorage { 
	constructor(props: IMyComponentProps) { 
		super(props); 
		this.state = { val: 1 } 
	}
	render() { 
		this.props.title; 
		this.state.val; 
		return `<div>组件</div>`; }getInfo(): string { return `组件:MyComponent,props:		${this.props},state:${this.state}`; 
	}
	save(data: string) { 
		// ... 存储 
	} 
}
  • 接口也可以继承
interface ILog { 
	getInfo(): string; 
}
interface IStorage extends ILog { 
	save(data: string): void; 
}

类与对象

  • 在 TypeScript 定义一个类的时候,其实同时定义了两个不同的类型
    • 类类型(构造函数类型)。TypeScript 中的类其实本质上还是一个函数,也称为构造函数,那么这个类或者构造函数本身也是有类型的,那么这个类型就是类的类型
    • 对象类型。就是 new 出来的实例类型
class Person { 
	// 属于类的 
	static type = '人'; 
	// 属于实例的 
	name: string; 
	age: number; 
	gender: string; 
	// 类的构造函数也是属于类的 
	constructor( name: string, age: number, gender: '男'|'女' = '男' ) { 
		this.name = name; 
		this.age = age; 
		this.gender = gender; 
	}
	public eat(): void { 
		// ... 
	} 
}
let p1 = new Person('xiaochen', 25, '男'); 
p1.eat(); 
Person.type;
  • 上面例子中,有两个不同的数据
    • Person 类(构造函数)
    • 通过 Person 实例化出来的对象 p1
  • 对应的也有两种不同的类型
    • 实例的类型( Person )
    • 构造函数的类型( typeof Person )
  • 用接口的方式描述如下:
interface Person { 
	name: string; 
	age: number; 
	gender: string; 
	eat(): void; 
}
interface PersonConstructor { 
	// new 表示它是一个构造函数 
	new (name: string, age: number, gender: '男'|'女'): PersonInstance; 
	type: string; 
}
  • 在使用的时候要格外注意
function fn1(arg: Person /*如果希望这里传入的Person 的实例对象*/) { 
	arg.eat(); 
}
fn1( new Person('', 1, '男') ); 
function fn2(arg: typeof Person /*如果希望传入的Person构造函数*/) { 
	new arg('', 1, '男'); 
}
fn2(Person);
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-01-03 15:59:25  更:2022-01-03 16:02:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 12:22:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码