TypeScript 类 第一章【类,继承,修饰符】

简介: TypeScript 类 第一章【类,继承,修饰符】

前言

hello world欢迎来到前端的新世界


😜当前文章系列专栏:Typescript

🐱‍👓博主在前端领域还有很多知识和技术需要掌握,正在不断努力填补技术短板。(如果出现错误,感谢大家指出)🌹

💖感谢大家支持!您的观看就是作者创作的动力


传统的JavaScript的程序使用函数和基于原型的继承来创建可重用的组件,但对于熟悉使用面向对象方式的程序员来讲就有些棘手,因为他们用的是基于类的继承并且对象是由类构建出来从ECMAScript 2015,也就是ECMAScript 6开始,JavaScript程序员将能够使用基于类的面向对象的方式。使用TypeScript,我们允许开发者现在就使用这些特性,并且编译后的JavaScript可以在所有主流浏览器和平台上运行,而不需要等到下个JavaScript的版本。

下面看一个使用类的例子:


class Greeter {<font></font>
    greeting: string;
    constructor(message: string) {
        this.greeting = message;<font></font>
    }<font></font>
    greet() {<font></font>
        return "Hello, " + this.greeting;<font></font>
    }<font></font>
}<font></font>
<font></font>
let greeter = new Greeter("world");


如果你使用过C#或Java,你会对这种语法非常熟悉。我们声明一个 Greeter类。这个类有3个成员:一个叫做greeting的属性,一个构造函数和一个greet方法。


你会注意到,我们在引用任何一个类成员的时候都用了this。它表示我们访问的是类的成员。


最后一行,我们使用new构造了Greeter类的一个实例。它会调用之前定义的构造函数,创建一个 Greeter类型的新对象,并执行构造函数初始化它。



继承

在TypeScript里,我们可以使用常用的面向对象模式。当然,基于类的程序设计中最基本的模式是允许使用继承来扩展现有的类。


看下面的例子:


class Animal {<font></font>
    name:string;
    constructor(theName: string) { this.name = theName; }<font></font>
    move(distanceInMeters: number = 0) {
        console.log(`${this.name} moved ${distanceInMeters}m.`);<font></font>
    }<font></font>
}<font></font>
<font></font>
class Snake extends Animal {
    constructor(name: string) { super(name); }<font></font>
    move(distanceInMeters = 5) {
        console.log("Slithering...");
        super.move(distanceInMeters);<font></font>
    }<font></font>
}<font></font>
<font></font>
class Horse extends Animal {
    constructor(name: string) { super(name); }<font></font>
    move(distanceInMeters = 45) {
        console.log("Galloping...");
        super.move(distanceInMeters);<font></font>
    }<font></font>
}<font></font>
<font></font>
let sam = new Snake("Sammy the Python");
let tom: Animal = new Horse("Tommy the Palomino");<font></font>
<font></font>
sam.move();<font></font>
tom.move(34);


这个例子展示了TypeScript中继承的一些特征,它们与其它语言类似。 我们使用 extends关键字来创建子类。你可以看到Horse和Snake类是基类Animal的子类,并且可以访问其属性和方法。


包含构造函数的派生类必须调用super(),它会执行基类的构造方法。


这个例子演示了如何在子类里可以重写父类的方法。 Snake类和Horse类都创建了move方法,它们重写了从Animal继承来的move方法,使得move方法根据不同的类而具有不同的功能。 注意,即使 tom被声明为Animal类型,但因为它的值是Horse,tom.move(34)会调用Horse里的重写方法:


Slithering...
Sammy the Python moved 5m.
Galloping...
Tommy the Palomino moved 34m.



公共,私有与受保护的修饰符


默认为public


在上面的例子里,我们可以自由的访问程序里定义的成员。 如果你对其它语言中的类比较了解,就会注意到我们在之前的代码里并没有使用 public来做修饰;例如,C#要求必须明确地使用public指定成员是可见的。 在TypeScript里,成员都默认为 public。


你也可以明确的将一个成员标记成public。 我们可以用下面的方式来重写上面的 Animal类:


class Animal {
    public name: string;
    public constructor(theName: string) { this.name = theName; }
    public move(distanceInMeters: number) {
        console.log(`${this.name} moved ${distanceInMeters}m.`);<font></font>
    }<font></font>
}<font></font>


理解private


当成员被标记成private时,它就不能在声明它的类的外部访问。比如:


class Animal {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}
new Animal("Cat").name; // Error: 'name' is private;


TypeScript使用的是结构性类型系统。 当我们比较两种不同的类型时,并不在乎它们从何处而来,如果所有成员的类型都是兼容的,我们就认为它们的类型是兼容的。


然而,当我们比较带有private或protected成员的类型的时候,情况就不同了。 如果其中一个类型里包含一个 private成员,那么只有当另外一个类型中也存在这样一个private成员, 并且它们都是来自同一处声明时,我们才认为这两个类型是兼容的。 对于 protected成员也使用这个规则。


下面来看一个例子,更好地说明了这一点:


class Animal {
    private name: string;
    constructor(theName: string) { this.name = theName; }<font></font>
}<font></font>
<font></font>
class Rhino extends Animal {
    constructor() { super("Rhino"); }<font></font>
}<font></font>
<font></font>
class Employee {
    private name: string;
    constructor(theName: string) { this.name = theName; }<font></font>
}<font></font>
<font></font>
let animal = new Animal("Goat");
let rhino = new Rhino();
let employee = new Employee("Bob");<font></font>
<font></font>
animal = rhino;<font></font>
animal = employee; // Error: Animal and Employee are not compatible


这个例子中有AnimalRhino两个类,RhinoAnimal类的子类。 还有一个 Employee类,其类型看上去与Animal是相同的。 我们创建了几个这些类的实例,并相互赋值来看看会发生什么。 因为 AnimalRhino共享了来自Animal里的私有成员定义private name: string,因此它们是兼容的。 然而

Employee却不是这样。当把Employee赋值给Animal的时候,得到一个错误,说它们的类型不兼容。 尽管 Employee里也有一个私有成员name,但它明显不是Animal里面定义的那个。


理解protected


protected修饰符与private修饰符的行为很相似,但有一点不同,protected成员在派生类中仍然可以访问。例如:


class Person {
    protected name: string;
    constructor(name: string) { this.name = name; }<font></font>
}<font></font>
<font></font>
class Employee extends Person {
    private department: string;<font></font>
<font></font>
    constructor(name: string, department: string) {
        super(name)
        this.department = department;<font></font>
    }<font></font>
<font></font>
    public getElevatorPitch() {
        return `Hello, my name is ${this.name} and I work in ${this.department}.`;<font></font>
    }<font></font>
}<font></font>
<font></font>
let howard = new Employee("Howard", "Sales");
console.log(howard.getElevatorPitch());
console.log(howard.name); // error


注意,我们不能在Person类外使用name,但是我们仍然可以通过Employee类的实例方法访问,因为Employee是由Person派生而来的。


构造函数也可以被标记成protected。 这意味着这个类不能在包含它的类外被实例化,但是能被继承。比如,


class Person {
    protected name: string;
    protected constructor(theName: string) { this.name = theName; }<font></font>
}<font></font>
<font></font>
// Employee can extend Person
class Employee extends Person {
    private department: string;<font></font>
<font></font>
    constructor(name: string, department: string) {
        super(name);
        this.department = department;<font></font>
    }<font></font>
<font></font>
    public getElevatorPitch() {
        return `Hello, my name is ${this.name} and I work in ${this.department}.`;<font></font>
    }<font></font>
}<font></font>
<font></font>
let howard = new Employee("Howard", "Sales");
let john = new Person("John"); // Error: The 'Person' constructor is protected


readonly修饰符


你可以使用readonly关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化。


class Octopus {<font></font>
    readonly name: string;<font></font>
    readonly numberOfLegs: number = 8;
    constructor (theName: string) {
        this.name = theName;<font></font>
    }<font></font>
}<font></font>
let dad = new Octopus("Man with the 8 strong legs");<font></font>
dad.name = "Man with the 3-piece suit"; // error! name is readonly.



后言

创作不易,要是本文章对广大读者有那么一点点帮助 不妨三连支持一下,您的鼓励就是博主创作的动力


目录
相关文章
|
6月前
|
JavaScript 前端开发 程序员
TypeScript 类
TypeScript 类
|
2月前
|
JavaScript 前端开发
Vue2整合TypeScript:借助vue-property-decorator以类模式编写组件
Vue2整合TypeScript:借助vue-property-decorator以类模式编写组件
178 3
|
3月前
|
JavaScript
typeScript进阶(13)_类与注意事项(八项特性)
TypeScript的类支持特性包括:构造函数、继承(使用`extends`)、公有/私有/受保护修饰符、只读修饰符、参数属性、存取器(getters/setters)、抽象类(用`abstract`声明)。类可用作类型。
29 0
typeScript进阶(13)_类与注意事项(八项特性)
|
6月前
|
JavaScript 前端开发 开发者
10.【TypeScript 教程】类(Class)
10.【TypeScript 教程】类(Class)
34 2
|
5月前
|
JavaScript 前端开发
TypeScript(七)类
TypeScript(七)类
41 0
|
6月前
|
JavaScript
TypeScript类
TypeScript类
|
6月前
|
JavaScript Java C#
typescript 类类型
typescript 类类型
|
2月前
|
JavaScript 前端开发 安全
深入理解TypeScript:增强JavaScript的类型安全性
【10月更文挑战第8天】深入理解TypeScript:增强JavaScript的类型安全性
63 0
|
2月前
|
JavaScript 前端开发 开发者
深入理解TypeScript:类型系统与实用技巧
【10月更文挑战第8天】深入理解TypeScript:类型系统与实用技巧
|
28天前
|
设计模式 JavaScript 安全
TypeScript性能优化及代码质量提升的重要性、方法与策略,包括合理使用类型注解、减少类型断言、优化模块导入导出、遵循编码规范、加强代码注释等
本文深入探讨了TypeScript性能优化及代码质量提升的重要性、方法与策略,包括合理使用类型注解、减少类型断言、优化模块导入导出、遵循编码规范、加强代码注释等,旨在帮助开发者在保证代码质量的同时,实现高效的性能优化,提升用户体验和项目稳定性。
42 6
下一篇
DataWorks