TypeScript----Class (下)
🔯 继承
继承在 TS 中的语法和 JS 没有两样,但是有一点是至关重要的:TS 强制派生类始终是基础类的子类型。
class Base { getSomething() { console.log('this is something ') } } class Derived extends Base { // 覆盖基础类的方法, 携带一个可选的参数 getSomething(name?: string) { if(name === undefined) { super.getSomething() }else { console.log(name.toUpperCase()) } } } const Inst = new Derived(); Inst.getSomething(); Inst.getSomething('apple');
派生类遵循基础类,并在实际开发中,通过基类引用派生类是常见的操作,尤其是编写库的时候,如果你读过React 或者 Vue 源码肯定见过这样的写法。
// 接着上一段代码 const OtherInst: Base = Inst; OtherInst.getSomething()
因为有了继承关系和子类关系,所以当派生类没有遵循基础类时,TS checker 将不会通过:
class Base { getSomething() { console.log('this is something ') } } class Derived extends Base { // 注意参数 name 是必要参数,这已经违背了基础类的规则 getSomething(name: string) { // Property 'getSomething' in type 'Derived' is not assignable to the same property in base type 'Base'. // Type '(name: string) => void' is not assignable to type '() => void'. } }
关于初始化顺序,先基础类后派生类,先初始化后构造。思考下面的执行顺序:
class Base { name = "base"; constructor() { console.log("My name is " + this.name); } } class Derived extends Base { name = "derived"; } // Prints What ?? base Or derived const d = new Derived();
🔯 类成员的可见性
🔯public
这是类成员默认的可见性,表示这个成员可以在任何位置被访问到。
class Greeter { public greet() { // 这里的 public 可以省略不写 console.log('hi') } } const g = new Greeter(); g.greet();
public 可以省略不写,除非为了保障一定的风格和可读性
🔯protected
当类成员使用了 protected 这个关键字,则意味着这个成员只能在派生类中使用,不用用于实例和外部调用。
class Greeter { public greet() { console.log('Hello,' + this.getName()) } protected getName() { // 这里使用了 protected 关键字,所有这个方法只能类和子类内部调用 return 'hi'; } } class SpecialGreeter extends Greeter { public howdy() { // 子类内部使用父类的 protected getName console.log('Howdy,' + this.getName()); } } const g = new SpecialGreeter(); g.greet(); // OK g.getName(); // BAD
但是这种限制不是一定的,在派生类中,可以把基础类中的 protected 成员 变为 public 成员 。
class Base { protected m = 10; protected printName() { console.log(this.m) } } class Derived extends Base { // 默认为 'public' m = 15; printName() { console.log('Change It!') } } const d = new Derived(); console.log(d.m); // 15 d.printName(); // Change It!
跨级使用受保护的成员
不同的面向对象的语言,对于是否可以通过基类直接访问受保护的成员各有不同,在 TS 中这样做是不允许的
class Base { protected x: number = 1; } class Derived1 extends Base { protected x: number = 5; } class Derived2 extends Base { fn1(other: Derived2) { other.x = 10; 👍 } fn2(other: Base) { other.x = 10; 👎
// Property 'x' is protected and only accessible through an instance of class 'Derived2'. This is an instance of class 'Base'. } }
🔯 private
private 类似于 protected,但是通过 private 修饰过的成员只能在基类中访问,派生类和实例都不允许访问。
class Base {
private x = 0;
}
const inst = new Bsse();
console.log(inst.x) 👎
class Derived extends Base {
showX() {
console.log(this.x) 👎
}
}
🔯 static 成员
类可以有自己的静态成员,可以通过类本身调用他们
class MyClass { static x = 0; static printX() { console.log(MyClass.x); } } MyClass.printX();
static 修饰符也可以和上面提到的可见性修饰符(public, protected, private)一起使用
class MyClass { private static x = 0; } console.log(MyClass.x) 👎 // Property 'x' is private and only accessible within class 'MyClass'.
🔯 静态块
静态块允许编写一系列具有自己作用域的语句,这些语句可以访问包含类中的私有字段。这意味着我们可以使用编写语句的所有功能编写初始化代码,不泄漏变量,并完全访问类的内部。
const loadLastInstances = () =>[] class Foo { static #count = 0; get count() { return Foo.#count; } static { try { const lastInstances = loadLastInstances(); Foo.#count += lastInstances.length; } catch {} } }
🔯 泛型类
类可以像接口一样具有泛型的定义,使用new实例化泛型类时,其类型参数的推断方式与函数调用中的相同:
class Box<Type> { contents: Type; constructor(value: Type) { this.contents = value; } } const b = new Box("hello!")
注意:不要在静态成员上使用类型,
class Box<Type> { static defaultValue: Type; // Static members cannot reference class type parameters. }
🔯 抽象类
可以把基类当作一个抽象类,基类中的方法也可以当作抽象方法,那么这个抽象类就不能直接实例化,而是充当其他派生类的基类。
abstract class Base { abstract getName(): string; // 方法的签名 printName() { console.log("Hello, " + this.getName()); } } const b = new Base(); 👎 class Derived extends Base { getName() { // 执行方法 return "world"; } } const d = new Derived(); 👍 d.printName();
posted on 2022-03-27 11:34 Deflect-o-Bot 阅读(57) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!