接口的作用:在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范;在程序设计里,接口起到限制和规范的作用。
接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,它只是规定这批类里必须提供某些方法,提供这些方法的类就可以满足实际需要。typescript中的接口类似于java,同时还增加了更灵活的接口类型。
属性接口
ts 自定义带参数的方法
function printS(s:string):void{
console.log(`print:${s}`);
}
printS('a')
ts 自定义方法对传入参数进行约束
function printS(o:{name:string,label:string}):void{ //函数参数对象只能有name、label属性
console.log(`print:${o.name}、${o.label}`);
}
// 参数顺序可以不一致
printS({name:'lucy',label:'good'}) //print:lucy、good
printS({name:'lucy',label:'good'}) //print:lucy、good
使用接口对传入参数进行约束
interface printInfo{ //必须只包含 name和label
name:string,
label:string
}
function printS(o:printInfo):void{
console.log(`print:${o.name}、${o.label}`);
}
// 这种写法不能穿多余参数,下面定义变量传参可以有多余参数
printS({name:'lucy',label:'good'}) //print:lucy、good
let obj = {
name:'lucy',
label:'good',
age:12 //函数里不能调用未在接口里定义的属性,最好传参时也不要设置
}
printS(obj) //print:lucy、good
接口里定义可选属性 ?:
interface printInfo{
name:string,
label?:string //label 是可选属性,可有可无
}
function getName(name:printInfo){
console.log(name);
}
getName({
name:'lucy'
})
例子🌰,原生js封装的ajax
interface Config{
type:string;
url:string;
data?:string;
dataType:string;
}
function ajax(config:Config){
var xhr = new XMLHttpRequest()
xhr.open(config.type,config.url,true)
xhr.send(config.data)
xhr.onreadystatechange = ()=>{
if(xhr.readyState==4 && xhr.status==200){
console.log('success!');
if(config.dataType=='json'){
console.log(JSON.parse(xhr.responseText));
}else{
console.log(xhr.responseText);
}
}
}
}
ajax({
type:'GET',
url:'http://127.0.0.1:3011/api/data',
dataType:'json'
})
可以找一个接口测试一下,如下图,使用封装的ajax请求成功
函数型接口
定义方法时使用,对方法传入的参数以及返回值进行约束
interface encrypt{
(key:string,value:string):string
}
var md5:encrypt = function(key:string,value:string):string{
return key+value
}
console.log(md5('lucy','good')); //lucygood
可索引接口
对数组的约束:
interface IArr{
[index:number]:string //索引为number类型,值为string类型
}
var arr:IArr = ["a","b"]
console.log(arr[0]);
对对象的约束:
interface IObj{
[index:string]:number //索引为string类型,值为number类型
}
var obj:IObj = {
name:1,
label:2
}
console.log(obj['name']);
类类型接口
对类的约束,和抽象类有点相似
类类型接口:
interface Animal{
name:string;
eat(str:string):void; //str 可以不传
}
class Dog implements Animal { //使用implements来实现接口
name:string;
constructor(name:string){
this.name = name
}
eat(){
console.log(`${this.name}吃肉`);
}
sleep(){
console.log('sleep');
}
}
let d = new Dog('小狗')
d.eat() //小狗吃肉
d.sleep() //sleep
class Cat implements Animal {
name:string;
constructor(name:string){
this.name = name
}
eat(food?:string){
console.log(`${this.name}吃${food}`);
}
}
let c = new Cat('小花')
c.eat('鱼') //小花吃鱼
c.eat() //小花吃undefined
抽象类接口:
abstract class Animal{
name:string;
constructor(name:string){
this.name = name
}
abstract eat():any;
}
class Dog extends Animal{
constructor(name:string){
super(name)
}
eat(food?:string){
if(food){
console.log(`${this.name}吃${food}`);
}else{
console.log(`${this.name}吃狗粮`);
}
}
}
let d = new Dog('旺财')
d.eat('肉') //旺财吃肉
d.eat() //旺财吃狗粮
接口和抽象类的区别:
定义上
:- 抽象类 abstract class 关键字;
- 接口 interface 关键字。
继承
:- 类可以继承一个类和多个接口;
- 接口不能继承类,接口可以继承多个接口。
方法实现上
:- 抽象类的可以定义抽象方法,也可以实现方法;
- 接口只能定义抽象方法,不存在方法的实现。
实现方式
:- 子类使用 extends 关键字来继承抽象类,子类若不是抽象类的话,它必须实现抽象类中的抽象方法;
- 子类使用关键字 implements 实现接口,必须提供接口中声明的属性和方法。
接口扩展:接口继承接口
interface Animal{
eat():void;
}
interface Person extends Animal{
work():void;
}
class Man implements Person{ //Man类必须要实现 eat 和 work 方法
name:string;
constructor(name:string){
this.name = name
}
eat(){
console.log('eat');
}
work(){
console.log('work');
}
}
let m = new Man('Tom')
m.eat() //eat
m.work() //work
再复杂一点,写一个类既继承父类,又实现接口
interface Animal{
eat():void;
}
interface Person extends Animal{
work():void;
}
class Helper {
name:string;
constructor(name:string){
this.name = name
}
help(){
console.log('help');
}
}
class Man extends Helper implements Person{ //Man类必须要实现 eat 和 work 方法
constructor(name:string){
super(name)
}
eat(){
console.log('eat');
}
work(){
console.log('work');
}
}
let m = new Man('Tom')
m.eat() //eat
m.work() //work
m.help() //help