TypeScript15:类的继承

一、继承的作用

继承可以描述类与类之间的关系。 

如果 A 和 B 都是类,并且可以描述为 A 是 B ,则 A 和 B 形成继承关系:

  •  B 是父类, A 是子类
  •  B 派生 A , A 继承 B 
  •  B 是 A 的基类, A 是 B 的派生类 

如果 A 继承自 B ,则 A 中自动拥有 B 中的所有成员。 

export class Tank { 
  x: number = 0
  y: number = 0
}
export class PlayerTank extends Tank {

}
const p = new PlayerTank();
console.log(p.x,p.y); // 0 0

1.成员的重写

(1)重写:子类中复用父类的成员。

  • 子类成员不能改变父类的成员。 
  • 无论是属性还是方法,子类都可以对父类的相应成员进行重写, 但是重写时,需要保证类型的匹配。
export class Tank { 
  x: number = 0
  y: number = 0
}
export class PlayerTank extends Tank {
  x: number = 20
  y: number = 20
}
const p = new PlayerTank();
console.log(p.x,p.y); // 20 20

(2)注意 this 关键字:在继承关系中, this 的指向是动态的,调用方法时,根据具体的调用者确定 this 指向。

export class Tank {
  name: string = '坦克'
  sayHello() {
    console.log(`你好,我是${this.name}`);
  }
}
export class PlayerTank extends Tank {
  name: string = '玩家坦克'
}
export class EnemyTank extends Tank {
  name: string = '敌方坦克'
}
const p = new PlayerTank();
const e = new EnemyTank();
p.sayHello() // 你好,我是玩家坦克
e.sayHello() // 你好,我是敌方坦克

(3) super 关键字:在子类的方法中,可以使用 super 关键字读取父类成员。 

export class Tank {
  name: string = '坦克'
  sayHello() {
    console.log(`你好,我是${this.name}`);
  }
}
export class PlayerTank extends Tank {
  name: string = '玩家坦克'
  life: number = 5
  test() { 
    super.sayHello()
  }
}
const p = new PlayerTank(); 
p.test() // 你好,我是玩家坦克

使用 this 可以达到同样的效果,但是两者有所区别:当子类中与父类中拥有同样的方法并且被调用时,通过 this 访问的是子类中的方法,通过 super 访问的是父类中的方法。

export class Tank {
  name: string = '坦克'
  sayHello() {
    console.log(`你好,我是${this.name}`);
  }
}
export class PlayerTank extends Tank {
  name: string = '玩家坦克'
  life: number = 5
  sayHello() {
    console.log(`啦啦啦`);
  }
  test() { 
    this.sayHello() // 啦啦啦
    super.sayHello() // 你好,我是玩家坦克
  }
}
const p = new PlayerTank(); 
p.test()

2.类型匹配

鸭子辨型法。

子类的对象,始终可以赋值给父类。面向对象中,这种现象,叫做里氏替换原则。

如果需要判断一个数据的具体子类类型,可以使用 instanceof 。 

下图中,可以为对象 p 赋值父类 Tank 类型。需要注意的是,在使用时,只能使用父类 Tank 里面已有的成员。

如果想要使用子类 PlayerTank 中独有的成员,可以为对象 p 赋值 PlayerTank 类型或者不限制类型。 

如果确定想要为对象赋值父类类型,又想要访问子类独有类型,可以使用 instanceof 对对象进行类型判断,之后再访问: 

export class Tank {
  name: string = '坦克'
  sayHello() {
    console.log(`你好,我是${this.name}`);
  }
}
export class PlayerTank extends Tank {
  name: string = '玩家坦克'
  life: number = 5
}
const p:Tank = new PlayerTank(); 
p.sayHello()
if (p instanceof PlayerTank) { 
  console.log(p.life); // 5
}

 3. protected 修饰符

访问权限修饰符: private public protected 

 protected :受保护的成员,只能在自身或子类中访问。 

编译结果中没有访问修饰符。 

export class Tank {
  protected name: string = '坦克'
  sayHello() {
    console.log(`你好,我是${this.name}`);
  }
}
export class PlayerTank extends Tank {
  life: number = 5
  test() { 
    console.log(this.name);
  }
}
const p = new PlayerTank(); 
p.test() // 坦克
export class Tank {
  protected name: string = '坦克'
  sayHello() {
    console.log(`你好,我是${this.name}`);
  }
}
export class PlayerTank extends Tank {
  protected name: string = '玩家坦克'
  life: number = 5
  test() { 
    console.log(this.name);
  }
}
const p = new PlayerTank(); 
p.test() // 玩家坦克

二、继承的单根性和传递性

单根性:每个类最多只能拥有一个父类。

传递性:如果 A 是 B 的父类,并且 B 是 C 的父类,则可以认为 A 也是 C 的父类。 

 此时, b 即拥有 EnemyTank 类的属性,也拥有 Tank 类的属性。

  • 26
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猛扇赵四那半好嘴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值