TypeScript 类

炒豆儿
• 阅读 1044

传统的js是使用函数和原型链的方式用来模拟类

es6中加入了类,class关键字

// 定义类
class Greeter {
    greeting: string;
    constructor(message: string){
        this.greeting = message;    // 使用this表示访问的是类成员 
    }
    greet() {
        return "Hello," + this.greeting;
    }
}

// 创建对象
let greeter = new Greeter("World");

编译后的js文件如下
es5

// 定义类
var Greeter = /** @class */ (function () {
    function Greeter(message) {
        this.greeting = message;
    }
    Greeter.prototype.greet = function () {
        return "Hello," + this.greeting;
    };
    return Greeter;
}());
// 创建对象
var greeter = new Greeter("World");
//# sourceMappingURL=out.js.map

es6

// 定义类
class Greeter {
    constructor(message) {
        this.greeting = message;
    }
    greet() {
        return "Hello," + this.greeting;
    }
}
// 创建对象
let greeter = new Greeter("World");
//# sourceMappingURL=out.js.map

继承

在ts中可以使用类似于Java中的类的继承。

// 定义类
class Animal {
    move(distanceInMeters: number = 0) {    // 定义一个方法
        console.log("class - Animal move 方法" + distanceInMeters);
    }
}

// 定义继承类
class Dog extends Animal {
    bark() {
        console.log("Dog!");
    }
}

const dog = new Dog();    // 创建给予Dog类的对象
dog.bark();    // 调用继承类的方法bark()
dog.move(10);    // 调用父类的move方法
dog.bark();
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    }
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
// 定义类
var Animal = /** @class */ (function () {
    function Animal() {
    }
    Animal.prototype.move = function (distanceInMeters) {
        if (distanceInMeters === void 0) { distanceInMeters = 0; }
        console.log("class - Animal move 方法" + distanceInMeters);
    };
    return Animal;
}());
// 定义继承类
var Dog = /** @class */ (function (_super) {
    __extends(Dog, _super);
    function Dog() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    Dog.prototype.bark = function () {
        console.log("Dog!");
    };
    return Dog;
}(Animal));
var dog = new Dog(); // 创建给予Dog类的对象
dog.bark(); // 调用继承类的方法bark()
dog.move(10); // 调用父类的move方法
dog.bark();
//# sourceMappingURL=out.js.map

超类

class Animal {
    name: string;
    constructor(theName: string){
        this.name = theName;
    }
    move(distanceInMeters: number = 0){
        console.log("distanceInMeters " + distanceInMeters);
    }
}

class Snake extends Animal {
    constructor(name: string){
        super(name);    // 调用父类的构造方法,在构造函数访问this之前,必须调用一次 super()
    };
    move(distanceInMeters = 45){    // 重写父类的move方法
        console.log("Galloping...");
        super.move(distanceInMeters);    // 调用父类的move方法
    }
};

class Horse extends Animal {
    constructor(name: string){
        super(name);    // 调用父类的构造方法
    }
    move(distanceInMeters = 45){    // 重写move方法
        console.log("Galloping...");
        super.move(distanceInMeters);    // 调用父类的move
    }
}

// 调用基类的派生类即Snake类,使用的是基类的构造方法,重写了基类的move方法,并在子类的move方法中调用了父类的move方法
let sam = new Snake("Sammy the Python");
let tom: Animal;    // 声明tom对象,其为Animal类
tom = new Horse("Tommy the Palomino");    // 此处赋值为Horse类,重写了Animal中的move方法

sam.move();
tom.move();
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    }
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var Animal = /** @class */ (function () {
    function Animal(theName) {
        this.name = theName;
    }
    Animal.prototype.move = function (distanceInMeters) {
        if (distanceInMeters === void 0) { distanceInMeters = 0; }
        console.log("distanceInMeters " + distanceInMeters);
    };
    return Animal;
}());
var Snake = /** @class */ (function (_super) {
    __extends(Snake, _super);
    function Snake(name) {
        return _super.call(this, name) || this;
    }
    ;
    Snake.prototype.move = function (distanceInMeters) {
        if (distanceInMeters === void 0) { distanceInMeters = 45; }
        console.log("Galloping...");
        _super.prototype.move.call(this, distanceInMeters); // 调用父类的move方法
    };
    return Snake;
}(Animal));
;
var Horse = /** @class */ (function (_super) {
    __extends(Horse, _super);
    function Horse(name) {
        return _super.call(this, name) || this;
    }
    Horse.prototype.move = function (distanceInMeters) {
        if (distanceInMeters === void 0) { distanceInMeters = 45; }
        console.log("Galloping...");
        _super.prototype.move.call(this, distanceInMeters); // 调用父类的move
    };
    return Horse;
}(Animal));
// 调用基类的派生类即Snake类,使用的是基类的构造方法,重写了基类的move方法,并在子类的move方法中调用了父类的move方法
var sam = new Snake("Sammy the Python");
var tom; // 声明tom对象,其为Animal类
tom = new Horse("Tommy the Palomino"); // 此处赋值为Horse类,重写了Animal中的move方法
sam.move();
tom.move();
//# sourceMappingURL=out.js.map

公有私有,保护修饰符

public 默认

public为默认

class Animal {
    public name: string;
    public constructor(theName: string){
        this.name = theName;
    }
    public move(distanceInMeters: number){
        console.log("move 方法");
    }
}
var Animal = /** @class */ (function () {
    function Animal(theName) {
        this.name = theName;
    }
    Animal.prototype.move = function (distanceInMeters) {
        console.log("move 方法");
    };
    return Animal;
}());
//# sourceMappingURL=out.js.map

private 保护成员

不能被外部访问
TypeScript 类

class Person {
    protected name: string;    // 保护成员,对外不可访问
    constructor(name:string){
        this.name = name;
    }
}

class Employee extends Person {
    private department: string;

    constructor(name:string, department:string){
        super(name);    // 调用父类的构造方法
        // 接着才能使用this
        this.department = department;
    }

    public getElevatorPitch(){
        return "hello !" + name;    // 通过实例访问父类的name
    }
}

let howard = new Employee("Howard", "sales");
console.log(howard.getElevatorPitch());
//console.log(howard.name);    //访问父类的,失败,不能直接被访问,但是能被派生方法所访问
PS C:\Users\mingm\Desktop\ts> tsc
Active code page: 65001
PS C:\Users\mingm\Desktop\ts>
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    }
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var Person = /** @class */ (function () {
    function Person(name) {
        this.name = name;
    }
    return Person;
}());
var Employee = /** @class */ (function (_super) {
    __extends(Employee, _super);
    function Employee(name, department) {
        var _this = _super.call(this, name) || this;
        // 接着才能使用this
        _this.department = department;
        return _this;
    }
    Employee.prototype.getElevatorPitch = function () {
        return "hello !" + name; // 通过实例访问父类的name
    };
    return Employee;
}(Person));
var howard = new Employee("Howard", "sales");
console.log(howard.getElevatorPitch());
//console.log(howard.name);    //访问父类的,失败,不能直接被访问,但是能被派生方法所访问
//# sourceMappingURL=out.js.map
// 构造函数使用保护
class Person {
    protected name: string;
    protected constructor(theName:string){    // 构造方法,进行保护
        this.name = theName;
    }
}

class Employee extends Person {
    private department: string;

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

    public getElevatorPitch() {
        return "hello" + this.department + this.name;
    }
}

let howard = new Employee("Howard", "Sales");

//let john = new Peron("John");    //错误,构造函数被保护,不能在外部访问
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    }
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
// 构造函数使用保护
var Person = /** @class */ (function () {
    function Person(theName) {
        this.name = theName;
    }
    return Person;
}());
var Employee = /** @class */ (function (_super) {
    __extends(Employee, _super);
    function Employee(name, department) {
        var _this = _super.call(this, name) || this;
        _this.department = department;
        return _this;
    }
    Employee.prototype.getElevatorPitch = function () {
        return "hello" + this.department + this.name;
    };
    return Employee;
}(Person));
var howard = new Employee("Howard", "Sales");
//let john = new Peron("John");    //错误,构造函数被保护,不能在外部访问
//# sourceMappingURL=out.js.map

readonly修饰符

将属性设置为只读

class Octopus {
    readonly name: string;    // 只读
    readonly numberOfLegs: number = 8; // 只读

    constructor(theName:string){
        this.name = theName;
    }
}
let dad = new Octopus("Hello world");

//dad.name = "Hello world";    //设置值。出错,由于为只读
var Octopus = /** @class */ (function () {
    function Octopus(theName) {
        this.numberOfLegs = 8; // 只读
        this.name = theName;
    }
    return Octopus;
}());
var dad = new Octopus("Hello world");
//dad.name = "Hello world";    //设置值。出错,由于为只读
//# sourceMappingURL=out.js.map

参数属性

class Octopus {
    readonly numberOfLegs: number = 9;
    constructor(readonly name:string){    // 直接定义参数属性

    }
}
var Octopus = /** @class */ (function () {
    function Octopus(name) {
        this.name = name;
        this.numberOfLegs = 9;
    }
    return Octopus;
}());
//# sourceMappingURL=out.js.map

通过get set获取属性

let passcode = "secret passcode";

class Employee {
    private _fullName: string;    // 保护成员一般下划线

    get fullName():string {    // get方法
        return this._fullName;
    }

    set fullName(newName:string){
        if (passcode && passcode == "code") {
            // 进行赋值操作
            this._fullName = newName;
        }else {
            console.log("出现重复")
        }
    }
}

let employee = new Employee();    // 创建对象
employee.fullName = "Bob";    //调用get方法
// 下面调用set方法
if(employee.fullName){
    console.log(employee.fullName);
}
PS C:\Users\mingm\Desktop\ts> tsc
Active code page: 65001
PS C:\Users\mingm\Desktop\ts>
var passcode = "secret passcode";
var Employee = /** @class */ (function () {
    function Employee() {
    }
    Object.defineProperty(Employee.prototype, "fullName", {
        get: function () {
            return this._fullName;
        },
        set: function (newName) {
            if (passcode && passcode == "code") {
                // 进行赋值操作
                this._fullName = newName;
            }
            else {
                console.log("出现重复");
            }
        },
        enumerable: true,
        configurable: true
    });
    return Employee;
}());
var employee = new Employee(); // 创建对象
employee.fullName = "Bob"; //调用get方法
// 下面调用set方法
if (employee.fullName) {
    console.log(employee.fullName);
}
//# sourceMappingURL=out.js.map

只能输出es5或更高的版本,不支持输出es3

静态属性

当类未被实例化的时候,可以直接访问的为静态属性

class Grid {
    static origin = { x: 0, y: 0 };    // 这里类似使用static 
    calculate(point:{x:number, y:number}){    // 在此处定义了point,
        let x = point.x - Grid.origin.x    // 前面访问的是poinyt定义的,后面访问的是static定义的origin
        let y = point.y - Grid.origin.y;    // 同理如上
        return point.x + point.y;    
    }
    constructor(public scale: number) { };
}

let grid1 = new Grid(1.0);// 对static进行赋值
let grid2 = new Grid(2.0);

// 访问
grid1.calculate({x:10, y:10});    
grid2.calculate({x:10, y:10});
var Grid = /** @class */ (function () {
    function Grid(scale) {
        this.scale = scale;
    }
    Grid.prototype.calculate = function (point) {
        var x = point.x - Grid.origin.x; // 前面访问的是poinyt定义的,后面访问的是static定义的origin
        var y = point.y - Grid.origin.y; // 同理如上
        return point.x + point.y;
    };
    ;
    Grid.origin = { x: 0, y: 0 }; // 这里类似使用static 
    return Grid;
}());
var grid1 = new Grid(1.0); // 对static进行赋值
var grid2 = new Grid(2.0);
// 访问
grid1.calculate({ x: 10, y: 10 });
grid2.calculate({ x: 10, y: 10 });
//# sourceMappingURL=out.js.map

抽象类

抽象类为其他派生类的基类。

抽象类不会被实例化

抽象类用于作为基类,派生出其他类使用。

// 定义抽象类
abstract class Department {
    constructor(public name:string){

    }

    // 定义实现的细节
    printName():void{
        console.log("实现细节");
    }

    // 定义抽象方法,该抽象方法必须在派生类中实现其具体的内容
    abstract printMeeting(): void;
}

class AccountingDepartemnt extends Department {
    constructor(){
        super("hello world");    // 调用基类的构造方法
    }

    // 对抽象方法进行完善
    printMeeting():void{
        console.log("完善!");
    }

    // 定义其余的方法
    generateReports():void{
        console.log("添加的其他方法")
    }
}

// 创建一个抽象类型的引用
let department: Department;    // 抽象类的引用,类似于定义,可以被抽象类的子类进行实例化,即分配内存空间,不能被抽象类进行实例化,因为抽象类不能分配内存空间,所以不能对抽象类进行new操作
department = new AccountingDepartemnt();    // 可以进行分配内存空间
department.printMeeting();    
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    }
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
// 定义抽象类
var Department = /** @class */ (function () {
    function Department(name) {
        this.name = name;
    }
    // 定义实现的细节
    Department.prototype.printName = function () {
        console.log("实现细节");
    };
    return Department;
}());
var AccountingDepartemnt = /** @class */ (function (_super) {
    __extends(AccountingDepartemnt, _super);
    function AccountingDepartemnt() {
        return _super.call(this, "hello world") || this;
    }
    // 对抽象方法进行完善
    AccountingDepartemnt.prototype.printMeeting = function () {
        console.log("完善!");
    };
    // 定义其余的方法
    AccountingDepartemnt.prototype.generateReports = function () {
        console.log("添加的其他方法");
    };
    return AccountingDepartemnt;
}(Department));
// 创建一个抽象类型的引用
var department; // 抽象类的引用,类似于定义,可以被抽象类的子类进行实例化,即分配内存空间,不能被抽象类进行实例化,因为抽象类不能分配内存空间,所以不能对抽象类进行new操作
department = new AccountingDepartemnt(); // 可以进行分配内存空间
department.printMeeting();
//# sourceMappingURL=out.js.map

构造函数

可以使用类似于java中的语法,进行声明构造函数

class Greeter{
    greeting: string;
    constructor(message:string){
        this.greeting = message;
    }
    // 类似于java中声明构造方法
    greet(){
        return "hello " + this.greeting;
    }
}

// 首先进行创建引用,类似于原生的var,仅仅声明,并未创建引用。但是必须进行声明,声明其为Greeter
let greeter: Greeter;
// 进行分配空间
greeter = new Greeter("world");
console.log(greeter.greet());

和使用抽象接口一样,当使用抽象接口的时候,必须要进行先创建引用,然后在分配空间
原生的如下

var i;  // 在栈上开辟一块空间,进行储存
i = new Greeter();  // 完成由栈到堆的指向,对象储存在堆中,当然啦,C++允许对象储存在栈中

必须进行两步。

关于C++堆和栈的类

静态建立

使用

Box Box

如上的方式,将会静态的建立一个对象
静态建立对象,将会由编译器在栈中分配内存空间。通过移动栈顶指针,挪出适当的位置,在内存空间上调用构造函数,形成一个栈对象,此方法为在栈中储存对象。

动态建立

使用

Box* Box = new Box();

如上的方式,将会动态的建立一个对象。
使用new操作运算符的时候,将会在堆中分配一块内存空间,完成由栈到对的指向。

类当做接口使用

接口,一种传入对象的规范,比喻,水管的水龙头。

类可以创建出任何类型

class Point{
    x: number;
    y: number;
}

interface Point3d extends Point{
    z: number;
}

let point3d:Point3d = {
    x:1,
    y:2,
    z:4
}

使用extends,进行创建接口

var Point = /** @class */ (function () {
    function Point() {
    }
    return Point;
}());
var point3d = {
    x: 1,
    y: 2,
    z: 4
};
//# sourceMappingURL=out.js.map
点赞
收藏
评论区
推荐文章
ZY ZY
4年前
js继承的几种方式
1.原型链继承原型链继承:想要继承,就必须要提供父类(继承谁,提供继承的属性)//父级functionPerson(name)//给构造函数添加参数this.namename;this.age10;this.sumfunction()console.log(this.name)//原
Easter79 Easter79
3年前
typescript类与继承
1/21、vscode配置自动编译341.第一步tscinti生成tsconfig.json改"outDir":"./js",5672、第二步任务运行任务监视tsconfig.json
Wesley13 Wesley13
3年前
java 中链表的实现
//数据类 class DATA2{String key;String name;int age;}//定义链表类class CLType{DATA2 nodedatanew DATA2();CLType nextNodenull;//下
Jacquelyn38 Jacquelyn38
4年前
你不可不知的JS面试题(第二期)
1、什么是继承?子类可以使用父类的所有功能,并且对功能进行扩展。新增方法改用方法(1)、ES6使用extends子类继承父类的方法。// 父类    class A        constructor(name)            this.name name;                getNa
Wesley13 Wesley13
3年前
ES6知识点整理之
ES6引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。//定义类classPoint{constructor(x,y){this.xx;this.yy;}toString(){
Easter79 Easter79
3年前
TypeScript 中的类和接口
在面向对象(OOP)编程中,经常会使用到class(类)和interface(接口)。在TypeScript(以下简称TS)中也引入了类和接口的概念,使得TS强大的类型检测机制更加完善。就像我们所知道的,一个类是一堆抽象概念的集合,我们可以从类的构造方法中创建出享有共同属性和方法的对象。一个接口所描述的是一个对象相关的属性和方法,但并不提供具体创建此对象实例
Stella981 Stella981
3年前
Javascript 是如何体现继承的 ?
js继承的概念js里常用的如下两种继承方式:原型链继承(对象间的继承)类式继承(构造函数间的继承) 由于js不像java那样是真正面向对象的语言,js是基于对象的,它没有类的概念。所以,要想实现继承,可以用js的原型prototype机制或者用apply和call方法去实现在面向对象的语言中,我们使用类来创建一个自定义对象
Stella981 Stella981
3年前
JavaScript中的类定义和继承实现
ES5中因为没有class关键字,所以创建类的方式是通过构造函数来定义的。我将一步步的用代码演示如何慢慢用原生的语法实现JS的类的定义和继承。希望大家喜欢。废话不多说,我们来看原生JavaScript定义类的方法。1\.最简单的类//类的构造函数functionPerson(){this.nam
Stella981 Stella981
3年前
Javascript中,实现类与继承的方法和优缺点分析
Javascript是一种弱类型语言,不存在类的概念,但在js中可以模仿类似于JAVA中的类,实现类与继承第一种方法:利用Javascript中的原型链1//首先定义一个父类23functionAnimal(name,age){4//定义父类的属性5thi
Wesley13 Wesley13
3年前
C++中类中范围解析运算符::和点运算符(.)
C 类成员函数类的成员函数是指那些把定义和原型写在类定义内部的函数,就像类定义中的其他变量一样。类成员函数是类的一个成员,它可以操作类的任意对象,可以访问对象中的所有成员。让我们看看定义的类Box,现在我们要使用成员函数来访问类的成员,而不是直接访问这些类的成员:classBox{public:double
Stella981 Stella981
3年前
Javascript定义类(class)的三种方法
在面向对象编程中,类(class)是对象(object)的模板,定义了同一组对象(又称"实例")共有的属性和方法。Javascript语言不支持"类",但是可以用一些变通的方法,模拟出"类"。一、构造函数法这是经典方法,也是教科书必教的方法。它用构造函数模拟"类",在其内部用this关键字指代实例对象。  function