TypeScript
Классы
Поиск…
Вступление
TypeScript, например ECMA Script 6, поддерживает объектно-ориентированное программирование с использованием классов. Это контрастирует со старыми версиями JavaScript, которые поддерживают только цепочку наследования на основе прототипов.
Поддержка классов в TypeScript аналогична поддержке классов, таких как Java и C #, в том, что классы могут наследовать от других классов, тогда как объекты создаются экземплярами класса.
Также похожие на эти языки классы TypeScript могут реализовывать интерфейсы или использовать дженерики.
Простой класс
class Car {
public position: number = 0;
private speed: number = 42;
move() {
this.position += this.speed;
}
}
В этом примере мы объявляем простой класс Car
. Класс состоит из трех членов: speed
частной собственности, position
публичной собственности и move
общедоступного метода. Обратите внимание, что каждый участник является общедоступным по умолчанию. Вот почему move()
является общедоступным, даже если мы не использовали ключевое слово public
.
var car = new Car(); // create an instance of Car
car.move(); // call a method
console.log(car.position); // access a public property
Основное наследование
class Car {
public position: number = 0;
protected speed: number = 42;
move() {
this.position += this.speed;
}
}
class SelfDrivingCar extends Car {
move() {
// start moving around :-)
super.move();
super.move();
}
}
В этом примере показано, как создать очень простой подкласс класса Car
с использованием ключевого слова extends
. Класс SelfDrivingCar
переопределяет метод move()
и использует реализацию базового класса, используя super
.
Конструкторы
В этом примере мы используем constructor
объявить общественное свойство position
и защищенное свойство speed
в базовом классе. Эти свойства называются параметрами . Они позволяют нам объявить параметр конструктора и член в одном месте.
Одна из лучших вещей в TypeScript - автоматическое назначение параметров конструктора соответствующему свойству.
class Car {
public position: number;
protected speed: number;
constructor(position: number, speed: number) {
this.position = position;
this.speed = speed;
}
move() {
this.position += this.speed;
}
}
Весь этот код можно возобновить в одном конструкторе:
class Car {
constructor(public position: number, protected speed: number) {}
move() {
this.position += this.speed;
}
}
И оба они будут переведены из TypeScript (время разработки и время компиляции) на JavaScript с одинаковым результатом, но значительно сократят количество кода:
var Car = (function () {
function Car(position, speed) {
this.position = position;
this.speed = speed;
}
Car.prototype.move = function () {
this.position += this.speed;
};
return Car;
}());
Конструкторы производных классов должны вызывать конструктор базового класса с помощью функции super()
.
class SelfDrivingCar extends Car {
constructor(startAutoPilot: boolean) {
super(0, 42);
if (startAutoPilot) {
this.move();
}
}
}
let car = new SelfDrivingCar(true);
console.log(car.position); // access the public property position
Accessors
В этом примере мы модифицируем пример «Simple class», чтобы разрешить доступ к свойству speed
. Атрибуты accesscript позволяют добавлять дополнительный код в getters или seters.
class Car {
public position: number = 0;
private _speed: number = 42;
private _MAX_SPEED = 100
move() {
this.position += this._speed;
}
get speed(): number {
return this._speed;
}
set speed(value: number) {
this._speed = Math.min(value, this._MAX_SPEED);
}
}
let car = new Car();
car.speed = 120;
console.log(car.speed); // 100
Абстрактные классы
abstract class Machine {
constructor(public manufacturer: string) {
}
// An abstract class can define methods of it's own, or...
summary(): string {
return `${this.manufacturer} makes this machine.`;
}
// Require inheriting classes to implement methods
abstract moreInfo(): string;
}
class Car extends Machine {
constructor(manufacturer: string, public position: number, protected speed: number) {
super(manufacturer);
}
move() {
this.position += this.speed;
}
moreInfo() {
return `This is a car located at ${this.position} and going ${this.speed}mph!`;
}
}
let myCar = new Car("Konda", 10, 70);
myCar.move(); // position is now 80
console.log(myCar.summary()); // prints "Konda makes this machine."
console.log(myCar.moreInfo()); // prints "This is a car located at 80 and going 70mph!"
Абстрактные классы - это базовые классы, из которых могут расширяться другие классы. Они не могут быть созданы сами собой (т. Е. Вы не можете сделать new Machine("Konda")
).
Двумя ключевыми характеристиками абстрактного класса в машинописном тексте являются:
- Они могут реализовывать свои собственные методы.
- Они могут определять методы, которые должны выполнять наследующие классы.
По этой причине абстрактные классы концептуально можно рассматривать как комбинацию интерфейса и класса .
Обезьяна исправляет функцию в существующий класс
Иногда полезно иметь возможность расширять класс новыми функциями. Например, предположим, что строка должна быть преобразована в строку верблюда. Поэтому нам нужно указать TypeScript, что String
содержит функцию, называемую toCamelCase
, которая возвращает string
.
interface String {
toCamelCase(): string;
}
Теперь мы можем исправить эту функцию в реализацию String
.
String.prototype.toCamelCase = function() : string {
return this.replace(/[^a-z ]/ig, '')
.replace(/(?:^\w|[A-Z]|\b\w|\s+)/g, (match: any, index: number) => {
return +match === 0 ? "" : match[index === 0 ? 'toLowerCase' : 'toUpperCase']();
});
}
Если это расширение String
загружено, оно можно использовать следующим образом:
"This is an example".toCamelCase(); // => "thisIsAnExample"
Transpilation
Учитывая класс SomeClass
, давайте посмотрим, как TypeScript транслируется в JavaScript.
Исходный код
class SomeClass {
public static SomeStaticValue: string = "hello";
public someMemberValue: number = 15;
private somePrivateValue: boolean = false;
constructor () {
SomeClass.SomeStaticValue = SomeClass.getGoodbye();
this.someMemberValue = this.getFortyTwo();
this.somePrivateValue = this.getTrue();
}
public static getGoodbye(): string {
return "goodbye!";
}
public getFortyTwo(): number {
return 42;
}
private getTrue(): boolean {
return true;
}
}
Источник JavaScript
Когда транслируется с использованием TypeScript v2.2.2
, вывод выглядит так:
var SomeClass = (function () {
function SomeClass() {
this.someMemberValue = 15;
this.somePrivateValue = false;
SomeClass.SomeStaticValue = SomeClass.getGoodbye();
this.someMemberValue = this.getFortyTwo();
this.somePrivateValue = this.getTrue();
}
SomeClass.getGoodbye = function () {
return "goodbye!";
};
SomeClass.prototype.getFortyTwo = function () {
return 42;
};
SomeClass.prototype.getTrue = function () {
return true;
};
return SomeClass;
}());
SomeClass.SomeStaticValue = "hello";
наблюдения
- Модификация прототипа класса завершается внутри IIFE .
- Переменные члена определяются внутри основной
function
класса. - Статические свойства добавляются непосредственно к объекту класса, тогда как свойства экземпляра добавляются к прототипу.