Классы
JavaScript фокусируется на функцих и наследовании, основанном на прототипах, для разработки многократно используемых компонентов. По этот подход довольно неуклюжий по сравнению с привычным объектоно-ориентированным программированием. На основе ECMAScript 6 следующая версия JavaScript будет позволять программистам применять ООП подход. В TypeScript такой подход можно рпименять уже сейчас и компилировать код в JavaScript, который уже сейчас будет работать на основной массе браузеров.Классы
Синтаксис описания класса и принцип работы такой же как в C# или Java. Рассмотрим простой пример.class Greeter { greeting: string; constructor(message: string) { this.greeting = message; } greet() { return "Hello, " + this.greeting; } } var greeter = new Greeter("world");
Наследование
В TypeScript используется подход классического ООП. Одной из основных возможностей является создание новыйх классов через наследование.class Animal { name:string; constructor(theName: string) { this.name = theName; } move(meters: number) { alert(this.name + " moved " + meters + "m."); } } class Snake extends Animal { constructor(name: string) { super(name); } move() { alert("Slithering..."); super.move(5); } } class Horse extends Animal { constructor(name: string) { super(name); } move() { alert("Galloping..."); super.move(45); } } var sam = new Snake("Sammy the Python"); var tom: Animal = new Horse("Tommy the Palomino"); sam.move(); tom.move(34);
Модификаторы доступа
По-умолчанию используется модификатор public, а для сокрытия свойства необходимо явно указать модификатор private.
class Animal { private name:string; constructor(theName: string) { this.name = theName; } move(meters: number) { alert(this.name + " moved " + meters + "m."); } }
Понимание private
TypeScript это система структурированных типов. Когда сравниваются два типа, независимо от того где и как они описаны и реализованы, если типы всех элементов этих типов совместимы, можно утверждать что сами эти типы совместимы. Но есть особенность с типами, имеющими приватные свойства. Для того, чтобы такие такие типы были совместимы, необходимо, чтобы приватные свойства были одного и того же происхождения.
class Animal { private name:string; constructor(theName: string) { this.name = theName; } } class Rhino extends Animal { constructor() { super("Rhino"); } } class Employee { private name:string; constructor(theName: string) { this.name = theName; } } var animal = new Animal("Goat"); var rhino = new Rhino(); var employee = new Employee("Bob"); animal = rhino; animal = employee; //error: Animal and Employee are not compatible
Свойства параметры
В TypeScript существует удобный способ описывать свойства типа через параметры конструктора.class Animal { constructor(private name: string) { } move(meters: number) { alert(this.name + " moved " + meters + "m."); } }
Методы доступа
TypeScript поддерживает методы доступа (get/set) как способ перехватывания доступа к свойствам объектов. Ниже показан пример без методов доступа.class Employee { fullName: string; } var employee = new Employee(); employee.fullName = "Bob Smith"; if (employee.fullName) { alert(employee.fullName); }
var passcode = "secret passcode"; class Employee { private _fullName: string; get fullName(): string { return this._fullName; } set fullName(newName: string) { if (passcode && passcode == "secret passcode") { this._fullName = newName; } else { alert("Error: Unauthorized update of employee!"); } } } var employee = new Employee(); employee.fullName = "Bob Smith"; if (employee.fullName) { alert(employee.fullName); }
Статические свойства
До сих пор шла речь о свойствах экземпларов классов, которые видны, когда инициализируется объект класса. Но можно использовать и статические свойства классов, которые видны через классе в целом (через тип класса), но через экземпляры. В примере ниже используется статическое свойство origin, единственное для всех экземпларов Grid. Каждый экземпляр получает доступ к статическому свойству через имя класса.class Grid { static origin = {x: 0, y: 0}; calculateDistanceFromOrigin(point: {x: number; y: number;}) { var xDist = (point.x - Grid.origin.x); var yDist = (point.y - Grid.origin.y); return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale; } constructor (public scale: number) { } } var grid1 = new Grid(1.0); // 1x scale var grid2 = new Grid(5.0); // 5x scale alert(grid1.calculateDistanceFromOrigin({x: 10, y: 10})); alert(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));
Продвинутые техники
Функции конструктора
КогдА описывается класс TypeScript, на самом деле происходит несколько описаний. Первая - это тип экземпляров класса.class Greeter { greeting: string; constructor(message: string) { this.greeting = message; } greet() { return "Hello, " + this.greeting; } } var greeter: Greeter; greeter = new Greeter("world"); alert(greeter.greet());
Второе что создается - это функция конструктор. Это функция, которая вызывается, когда создается экземпляр класса через 'new'. Чтобы увидеть как это работает на практике, рассмотрим JavaScript код, сгенерированный этим примером.
var Greeter = (function () { function Greeter(message) { this.greeting = message; } Greeter.prototype.greet = function () { return "Hello, " + this.greeting; }; return Greeter; })(); var greeter; greeter = new Greeter("world"); alert(greeter.greet());
Следующий пример показывает разницу.
class Greeter { static standardGreeting = "Hello, there"; greeting: string; greet() { if (this.greeting) { return "Hello, " + this.greeting; } else { return Greeter.standardGreeting; } } } var greeter1: Greeter; greeter1 = new Greeter(); alert(greeter1.greet()); var greeterMaker: typeof Greeter = Greeter; greeterMaker.standardGreeting = "Hey there!"; var greeter2:Greeter = new greeterMaker(); alert(greeter2.greet());
Далее класс используется напрямую. Создается переменная 'greeterMaker', которая содержит сам класс, или, другими словами, функцию конструктор. Конструкция 'typeof Greeter' создает объект типа класса, но не объект класса. Этот объект будет содержать все статические свойства класса и функцию конструктора. А далее создается экземпляр класса через 'new greeterMaker()'.
Использование класса как интерфейса
Описание класса делает две вещи: описывающий экземпляры класса тип и функцию конструктора. Так как классы создают типы, можно их использовать таким эе образом как интерфейсы.class Point { x: number; y: number; } interface Point3d extends Point { z: number; } var point3d: Point3d = {x: 1, y: 2, z: 3};
Комментариев нет :
Отправить комментарий
Примечание. Отправлять комментарии могут только участники этого блога.