抽象类以及接口(interface)

抽象类

  • 我们一般不希望使用父类来创造对象,因为父类的作用是专门被别的类继承的,因此就衍生出抽象类这一关键字了:abstract, 一般在class声明类之前添加这一关键字,如下所示:
/* ------- 抽象类 --------*/
abstract class Animal {
name:string;//创建属性
// 创建构造函数
constructor(name:string){
this.name = name;
}
}
  • 抽象类和其他的类区别是不大的,只是不能用来创建实例对象,也就是说,抽象类是专门用来继承的类(专门用来当父类的)

  • 抽象类中可以添加抽象方法:

    • 抽象方法同样是使用abstract关键字开头,但是没有函数体
    • 抽象方法只能定义在抽象类中,且继承它的子类必须对该方法进行重写
/* ------- 抽象方法 --------*/
abstract class Animal {
name:string;//创建属性
// 创建构造函数
constructor(name:string){
this.name = name;
}

/* ---- 抽象方法 ---- */
sayhello();//没有函数体
}

// 创建子类继承该父类时
class dog entends Animal{
// 对其抽象方法进行重写
sayhello(){
console.log('汪汪汪!')
}
}

代码展示:

/* ------------------------- 抽象类 -------------------------------*/ 
(function () {
/*
* 以abstract开头的类是抽象类,
* 抽象类和其他类区别不大,只是不能用来创建对象
* 抽象类就是专门用来被继承的类
*
* 抽象类中可以添加抽象方法
* */
abstract class Animal {
name: string;

constructor(name: string) {
this.name = name;
}

// 定义一个抽象方法
// 抽象方法使用 abstract开头,没有方法体
// 抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
abstract sayHello():void;//设置为无返回值
}

class Dog extends Animal{
// 对抽象方法进行重写(不重写就会报错!)
sayHello() {
console.log('汪汪汪汪!');
}

}

// 输出结果
const dog = new Dog('旺财');
console.log(dog);
dog.sayHello();
})();

接口(interface)

  • 所谓的接口其实就是一种用于定义一个类或者对象的结构的关键字,与type有点相似,不过type的用法更为广泛罢了
  • 它的作用类似于抽象类,不同点在于接口中的所有方法和属性都是没有实值的,换句话说接口中的所有方法都是抽象方法。接口主要负责定义一个类的结构,接口可以去限制一个对象的接口,对象只有包含接口中定义的所有属性和方法时才能匹配接口。同时,可以让一个类去实现接口,实现接口时类中要保护接口中的所有属性。
  • 在Ts中,我们可以通过typeinterface的方式去定义类型,一般情况下通过interface接口的方法定义的类型都可以通过type去定义。注意type要添加等号。Interface定义类型不需要添加等号。

type的用法

/* -------- type -------- */ 
// 1.我们可以使用type去定义变量类型
type a = string;
const b:a = '你好!'//此时的a就作为字符串变量类型来使用了
console.log(b);

// 2.我们可以使用type来定义对象类型
type myType = {
name:string;
age:number;
}

// 使用我们定义好的对象类型去创建对象
const myObj:myType = {
name:'小明',
age:12
}
console.log(myObj);

接口(interface)与type的相同点与不同点

  • 相同点:

    • 接口(interface)和type都可以用于类型声明去使用,不过前者只能用于类或对象的声明
  • 不同点:

    • 接口(interface)可以同时声明多个类或对象但使用一个变量名,结果则是将这些类或对象里面的属性叠加使用,但是type不能使用同一个属性名去声明多个变量
    • 接口(interface)在定义类时可以去限制类的结构,接口中所有的的属性都不能有实际值(不能赋值,只能定义属性),接口只定义对象的结构,不考虑实际值并且在接口中的所有方法都是抽象方法(这一点与抽象类中的抽象方法比较相像,但是抽象类中既可以有抽象方法,也可以有实际方法)

接口的基本使用

  1. 接口(interface)可以向现有类型添加新字段interface可以通过定义同名的方式去扩展字段,类型别名type是不能通过同名的方式去进行扩展的。
/* -------- 向现有的类型添加新字段 ------*/
// 接口1
interface myInterface {
name: string;
age: number;
}

// 接口2
interface myInterface {
gender: string;
}

// 接口1+接口2(属性或方法的拼接)
const obj: myInterface = {
name: 'sss',
age: 111,
gender: '男'
}
  1. Interface扩展接口:可以在interface后面添加关键字extends去扩展接口。类型别名type需要使用&符号去扩展接口
/* ---------- 扩展接口(inetrface) -----------*/
interface Animal{
name:string
}
interface Bear extends Animal{
honey:boolean
}
//声明一个类型为Bear类型的对象,要求既要有name,也要有honey。说明用extends扩展接口成功
const bear:Bear={
name:'winie',
honey:true
}
console.log(bear.name);
console.log(bear.honey);


/*---------- type扩展类型 ------------- */
type Animal={
name:string
}
//给Animal扩展接口
type Bear=Animal&{
honey:boolean
}
const bear:Bear={
name:'winie',
honey:true
}
  1. 创建类去继承接口(interface)时,需要使用implements关键字
/*
* 接口可以在定义类的时候去限制类的结构,
* 接口中的所有的属性都不能有实际的值
* 接口只定义对象的结构,而不考虑实际值
* 在接口中所有的方法都是抽象方法
*
* */
interface myInter{
name: string;//不能赋实际值

sayHello():void;//不能有函数体
}

/*
* 定义类时,可以使类去实现一个接口,
* 实现接口就是使类满足接口的要求(属性和方法必须与接口的结构保持一致)
* */

// 相较于继承类的extends,使用接口则是使用implements关键字
class MyClass implements myInter{
name: string;

constructor(name: string) {
this.name = name;
}

sayHello(){
console.log('大家好~~');
}
}
  1. 函数类型接口
  • 对方法传入的参数以及返回值进行约束
interface encrypt {
// 限制函数接口的形参输入和返回值输出
(key: string, value: string): string;
}

var md5: encrypt = function(key: string, value: string) {
return key + value;
}

console.log(md5('张', '三'));//成功输出!
  1. 可索引接口
  • 对数组和对象的约束
// 数组的约束
interface UserArr {
// [索引]:值
// 限制数组的索引值为数值型,但是数组里面的元素需为字符型
[index: number]: string;
}
const arr: UserArr = ['111', '222'];

// 对象的约束
interface UserObj {
// 限制对象的属性键名为字符型,但是对象的属性键值需为数值型
[index: string]: number;
}
const obj: UserObj = {
name: 123,
age: 321
}