TypeScript——接口和多态(接口定义函数变量类型、接口与对象、接口与数组、接口继承接口、类实现接口、泛型函数类型接口、接口与泛型、接口变量指向实现类对象、多态)

目录

 接口和多态

 一、接口定义函数变量类型

二、接口与对象

三、接口与数组

 四、接口继承接口

五、类实现接口

六、 泛型函数类型接口(见泛型章节 )

七、接口与泛型

八、接口变量指向实现类对象

九、多态

1 概念

2 接口变量实现多态

 3 父类变量+重写实现多态


 接口和多态

接口是一种自定义类型, 也就是类型了, 所以不但可以声明变量的类型,也可以声明函数参数(也是变量类型),函数返回值的类型

 一、接口定义函数变量类型

//函数类型接口
interface addType {
	(bValue: number, secValue: number):number
}
function add(x: number, y: number): number {
	return x + y;
}
let myadd1:addType = add;

let myadd2:addType = (x:number, y:number):number=>{
	return x+y;
}

二、接口与对象

(1)对象是字面量对象, 对象中成员必须与接口中声明的成员完全相同,不可多,也不可少

interface IPerson { 
    firstName:string, 
    lastName:string, 
    sayHi: ()=>string ,
    [prop:string]:any;//你可以随便扩展    值是任意类型   的   任意属性
} 

let teacher:IPerson = { 
    firstName:"Tom",
    lastName:"Hanks", 
    sayHi: ():string =>{return "Hi there"} 
} 
console.log(teacher);



以下代码也是对的
let teacher: { 
    firstName:string, 
    lastName:string, 
    sayHi: ()=>string 
} = { 
    firstName:"Tom",
    lastName:"Hanks", 
    sayHi: ():string =>{return "Hi there"} 
} 

(2)对象是通过new 出的对象,  对象中成员必须包含接口中声明的成员不可少,但是**可以增加接口中未声明的成员**

interface IPerson { 
    firstName:string, 
    lastName:string, 
    sayHi: ()=>string 
} 

class Teacher {
	firstName:string="小五";
	lastName:string="小二";
	age:number= 30; //接口中没有声明,但是不会错
	sayHi():string {
		return "Hi there";
	} 
}

let teacher:IPerson = new Teacher();
console.log(teacher);

以下代码也是对的
let teacher:{ 
    firstName:string, 
    lastName:string, 
    sayHi: ()=>string 
}  = new Teacher();

(3)类型断言情况下。对象中成员只能是接口中声明过的成员,但是可少

对于下面示例中stu对象中的成员可以包含firstName,lastName,sayHI, 可以少,不能出现接口中没有出现过的

interface IPerson { 
    firstName:string, 
    lastName:string, 
    sayHi: ()=>string 
} 
let stu:IPerson = <IPerson> {};  


stu.firstName = "司空";
stu.sayHi = ():string =>{return "Hi there"} 
console.log(stu);
//stu.xx = "dfds"//错,因为接口中没有出现过

三、接口与数组

接口可以规定数组中元素的索引类型和元素类型,先看一个与默认情况相同的示例

//规定以number为元素索引、string为元素类型
interface Inamelist { 
	[index:number]: string
} 

let list: string[] = ["John","Bran"] 
list[2] = "jeep";
console.log(list);

console.log(list[0]);
console.log(list[1]);
console.log(list[2]);

也可以使用非number类型为元素索引

//规定以string为元素索引、string为元素类型
interface Inamelist {
    [index: string]: string
}
let list: Inamelist = [] as unknown as Inamelist;
list['a'] = "好的";
list['b'] = "不错的";
console.log(list);
console.log(list['a']);//好的
console.log(list["b"]);//不错的

 四、接口继承接口

接口继承接口后,子接口就除了自身接口声明之外还包含了父接口声明

interface Person { 
   age:number 
} 
 
interface Musician extends Person { 
   instrument:string 
} 

接口继承接口是可以多继承的

interface IParent1 {
    v1:number 
} 
interface IParent2 {
    v2:number 
} 
//Iparent1和Iparent2顺序是无关仅要的
interface Child extends IParent1, IParent2 { 
	v3:string
} 

五、类实现接口

> 类可以实现接口,并可以多实现
> 类实现接口后,类体中必须实现接口所有字段和方法,当然类可以扩展自己本质的成员

interface IShape { 
   draw():void; 
   size:number;
}
interface IName {
	name: string;
}
class Circle implements IShape, IName { 
   public size:number = 30;
   public name:string = "圆";
   public draw():void { 
      console.log("会绘制一个"+this.name); 
   } 
   public show() {
	   console.log("本来是Circle");
   }
}
let c:Circle = new Circle();
c.draw();
c.size = 31;
c.name = "四边型";
c.show();

类可以继承父类的同时实现接口

interface IShape { 
   draw():void; 
   size:number;
}
interface IName {
	name: string;
}
class Shape {
	public showArea():void {
		console.log("面积是?平方")
	}
}
class Circle extends Shape implements IShape, IName { 
   public size:number = 30;
   public name:string = "圆";
   public draw():void { 
      console.log("会绘制一个"+this.name); 
   } 
   public show() {
	   console.log("本来是Circle");
   }
}
let c:Circle = new Circle();
c.draw();
c.size = 31;
c.name = "四边型";
c.showArea();
c.show();

六、 泛型函数类型接口(见泛型章节 )

//泛型函数类型接口1
interface GenericIdentityFn1 {
	(arg: T): T;
}
//泛型类函数型接口2
interface GenericIdentityFn2<T> {
    (arg: T): T;
}

七、接口与泛型

八、接口变量指向实现类对象

接口变量可以引用接口实现类对象, 但是只能访问接口中声明过的成员, 接口变量也可赋值为null或undefined, 

如果想使用此接口变量访问所有对象成员,那么可以对接口变量进行"类型断言"为对象所属类的类型。

interface IShape {
    draw():void; 
    size:number;
 }
 interface IName {
     name: string;
 }
 class Circle implements IShape, IName {
    size:number = 30;
    name:string = "圆";
    draw():void { 
       console.log("会绘制一个"+this.name); 
    } 
    show() {
        console.log("本来是Circle");
    }
 }
 let c:IShape = new Circle();
 c.draw();//对,因为IShape中出现过
 c.size = 31;//对,因为IShape中出现过
 //c.name = "四边型";//错
 //c.show();//错
 let c2 = <Circle>c;//类型断言
 c2.name = "四边型";//对
 c2.show();//对

九、多态

1 概念

  • 多态概念: 一种状态多种表现形式

  • 方法中this在编译时并不知道是哪个对象,执行过程中动态确定, 因为是在执行过程中确定的this,所以this属于运行时多态。

  • "接口变量指向实现类对象"或"父类指向子类对象+重写",可以实现运行时多态。

  • 有了接口变量引用对象,或父类变量引用子类对象,可以非常清晰的代码实现动态代理设计模式。

2 接口变量实现多态

多态:程序设定的标准,可以实现出多种满足这个标准的方案

下面示例, 在myshow方法中的 "a.show()"在编译的时候并不确定是执行X中的show()还是执行Y中的show(),还是其它类中的show, 只有运行过程中才能确定,完美实现动态多态性

interface A {
	show():void;
}
class X implements A {
	show() {
		console.log("这是X的show()")
	}
}
class Y implements A {
	show() {
		console.log("这是Y的show()")
	}
}
class Test {
	myshow(a: A) { //a=new X()  a=new Y()
		a.show();
	}
}
let x = new X();
let y = new Y();
let t = new Test();
t.myshow(x);//这是X的show()
t.myshow(y);//这是Y的show()

 3 父类变量+重写实现多态

下面示例中, 同样 myshow方法中的 "a.show()" 在运行过程中才知道是调用哪个类中的show()

class A {
	show() {
		console.log("A中的show")
	}
}
class X extends A {
	show() {
		super.show()
		console.log("这是X的show()")
	}
}
class Y extends A {
	show() {
		super.show();
		console.log("这是Y的show()")
	}
}
class Test {
	myshow(a: A) {//a=new A() a=new X(); a=new Y();
		a.show();
	}
}
let y = new Y();
let t = new Test();
t.myshow(new X());//这是X的show()
t.myshow(new Y());//这是Y的show()
t.myshow(new A());//主是A的show()

猜你喜欢

转载自blog.csdn.net/qq_52301431/article/details/127048619