携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情
接口
约束对象结构
之前我们学了类型注解,直接在对象名后写类型注解的坏处:
1、代码结构不简洁。
2、无法复用类型注解。例如我们看以下代码:
let p1: {
name: string
age: number
sayHello: () => void
} = {
name: '孙悟空',
age: 18,
sayHello() {
console.log("Hello 悟空");
}
}
let p2: {
name: string
age: number
sayHello: () => void
} = {
name: '八戒',
age: 16,
sayHello() {
console.log("Hello 八戒");
}
}
这种情况就用到了接口,接口:为对象的类型注解命名,并为你的代码建立契约来约束对象的结构。我们使用接口修改以上代码:
interface IUser {
name: string
//这个属性可有可无
age?: number
sayHello: () => void
}
let p1: IUser = {
name: '孙悟空',
sayHello() {
console.log("Hello 悟空");
}
}
let p2: IUser = {
name: '八戒',
age: 16,
sayHello() {
console.log("Hello 八戒");
}
}
console.log(p2.name)
p2.name="沙僧"
console.log(p2.name)
现在的属性是可读可写的,如果不想修改可以增加 readonly
interface IUser {
readonly name: string
age: number
sayHello: () => void
}
再尝试修改 name 属性就会报错:
接口在类中的作用
其实接口和抽象类非常相似,区别有两个:
1、抽象类能有抽象方法也可以有普通方法,而接口中的方法都是抽象方法
2、抽象类使用 extends 继承,接口使用implements实现
(function () {
/********* 例子 1 *********/
//先演示描述一个对象的类型
type myType = {
name: string,
age: number
};
const obj: myType = {
name: "张三",
age: 23
};
//接口在类中的作用就是用来定义一个类的结构
//用来定义一个类中应该有哪些类型和方法
//也可以当作类型声明来使用,和上边的作用一样
interface myInterface {
name: string;
age: number;
}
//可以声明相同的接口
interface myInterface {
gender: string;
}
//那么这个obj2里边就是上边接口的和
const obj2: myInterface = {
name: "李四",
age: 24,
gender: "男"
}
/********* 例子 2 *********/
//接口可以在定义类的时候限制类的结构
// 接口中所有属性都不能有实际值
//接口只定义对象的结构,而不考虑实际值
//在接口中所有的方法都是抽象方法
interface myInter {
name: string;
sayHello(): void
}
//定义一个类实现一个接口
class MyClass implements myInter{
name: string;
constructor(name:string) {
this.name = name;
}
sayHello(): void {
console.log("hello")
}
}
})();
接口也可以继承其他接口,使用关键字 extends
函数类型
定义一个接口,用来做为某个函数的类型使用
interface ISearchFunc {
// 定义一个调用签名
(source: string, subString: string): boolean
}
// 定义一个函数,类型就是上边的接口
const searchString: ISearchFunc = function (source: string, subString: string): boolean {
// 在source中查找substring
return source.search(subString) > -1
}
console.log(searchString('hello,world', 'hello'))//true
属性的封装
(function () {
//定义一个表示人的类
class Person {
//TS可以在属性前添加属性修饰符
//public(共有)
//private(私有)可以添加方法,get、set方法
//protect 只能在当前类和当前类的子类中使用
public name: string;
private age:number;
constructor(name: string,age:number) {
this.name = name;
this.age = age;
}
getAge(){
return this.age;
}
setAge(age:number){
//判断年龄是否合法
if(age>=0){
this.age = age;
}
}
}
const person = new Person("孙悟空",18);
//现在的属性都是在对象中设置的,属性可以被任意修改,这样非常不安全
person.name = "八戒";
//所以可以把属性改为private,然后增加get、set方法
person.setAge(20);
console.log(person);
})();
TS 中设置 getter 方法的方式
(function () {
class Person {
private _name: string;
private _age: number;
constructor(_name: string, _age: number) {
this._name = _name;
this._age = _age;
}
//TS 中getter方法
get name() {
return this._name
}
set name(name: string) {
this._name = name;
}
get age() {
return this._age;
}
set age(age: number) {
if (age > 0) {
this._age = age;
}
}
}
const person = new Person("孙悟空", 18);
person.name = "八戒";
person.age = -22;
console.log(person)
})();
可以将属性直接定义在构造函数中
(function () {
class Person {
//可以将属性直接定义在构造函数中
constructor(public name: string, public age: number) {
}
}
const person = new Person("孙悟空", 18);
console.log(person.name);//打印出孙悟空
})();