Инструменты пользователя

Инструменты сайта


typescript:types:interface

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
typescript:types:interface [2023/01/29 20:48]
werwolf
typescript:types:interface [2023/01/29 20:50] (текущий)
werwolf
Строка 35: Строка 35:
 В TypeScript интерфейс объявляется с помощью ключевого слова ''​interface'',​ после которого указывается идентификатор (имя), за которым следует тело, заключенное в фигурные скобки,​ содержащее описание. В TypeScript интерфейс объявляется с помощью ключевого слова ''​interface'',​ после которого указывается идентификатор (имя), за которым следует тело, заключенное в фигурные скобки,​ содержащее описание.
  
-<​code>​+<​code ​javascript>
 interface Identifier { interface Identifier {
   // тело интерфейса   // тело интерфейса
Строка 43: Строка 43:
 Объявление интерфейса возможно как в контексте модуля,​ так и в контексте функции или метода. Объявление интерфейса возможно как в контексте модуля,​ так и в контексте функции или метода.
  
-<​code>​+<​code ​javascript>
 interface Identifier {} // контекст модуля interface Identifier {} // контекст модуля
  
Строка 63: Строка 63:
 Первый вид конвенций родом из языка Java — они предлагают именовать интерфейсы точно так же, как и классы. Допускаются имена прилагательные. Первый вид конвенций родом из языка Java — они предлагают именовать интерфейсы точно так же, как и классы. Допускаются имена прилагательные.
  
-<​code>​+<​code ​javascript>
 interface Identifier {} interface Identifier {}
 </​code>​ </​code>​
Строка 69: Строка 69:
 Второй вид предлагает использовать конвенции языка C#, по которым интерфейсы именуются так же, как классы,​ но с префиксом ''​I'',​ что является сокращением от Interface. Такой вид записи получил название “венгерская нотация” в честь программиста венгерского происхождения,​ работавшего в компании MicroSoft. Допускаются имена прилагательные. Второй вид предлагает использовать конвенции языка C#, по которым интерфейсы именуются так же, как классы,​ но с префиксом ''​I'',​ что является сокращением от Interface. Такой вид записи получил название “венгерская нотация” в честь программиста венгерского происхождения,​ работавшего в компании MicroSoft. Допускаются имена прилагательные.
  
-<​code>​+<​code ​javascript>
 interface IIdentifier {} interface IIdentifier {}
 </​code>​ </​code>​
Строка 81: Строка 81:
 Класс, реализующий интерфейс,​ обязан реализовывать его в полной мере. Любой класс, который хочет реализовать интерфейс,​ должен указать это с помощью ключевого слова ''​implements'',​ после которого следует идентификатор реализуемого интерфейса. Указание реализации классом интерфейса располагается между идентификатором класса и его телом. Класс, реализующий интерфейс,​ обязан реализовывать его в полной мере. Любой класс, который хочет реализовать интерфейс,​ должен указать это с помощью ключевого слова ''​implements'',​ после которого следует идентификатор реализуемого интерфейса. Указание реализации классом интерфейса располагается между идентификатором класса и его телом.
  
-<​code>​+<​code ​javascript>
 interface IAnimal { interface IAnimal {
   nickname: string;   nickname: string;
Строка 97: Строка 97:
 Один класс может реализовывать сколько угодно интерфейсов. В этом случае реализуемые интерфейсы должны быть перечислены через запятую. Один класс может реализовывать сколько угодно интерфейсов. В этом случае реализуемые интерфейсы должны быть перечислены через запятую.
  
-<​code>​+<​code ​javascript>
 interface IAnimal {} interface IAnimal {}
 interface IOviparous {} // указывает на возможность откладывать яйца interface IOviparous {} // указывает на возможность откладывать яйца
Строка 106: Строка 106:
 В случае,​ когда класс расширяет другой класс, указание реализации (''​implements''​) следует после указания расширения (''​extends''​). В случае,​ когда класс расширяет другой класс, указание реализации (''​implements''​) следует после указания расширения (''​extends''​).
  
-<​code>​+<​code ​javascript>
 interface IAnimal {} interface IAnimal {}
 interface IOviparous {} interface IOviparous {}
Строка 121: Строка 121:
 Несмотря на то, что в интерфейсе можно декларировать поля и методы,​ в нем нельзя декларировать свойства ''​get''​ и ''​set''​ (аксессоры). Но, несмотря на это, задекларированное в интерфейсе поле может быть совместимо не только с полем, но и аксессорами. При этом нет разницы,​ будет в объекте объявлен getter, setter или оба одновременно. Несмотря на то, что в интерфейсе можно декларировать поля и методы,​ в нем нельзя декларировать свойства ''​get''​ и ''​set''​ (аксессоры). Но, несмотря на это, задекларированное в интерфейсе поле может быть совместимо не только с полем, но и аксессорами. При этом нет разницы,​ будет в объекте объявлен getter, setter или оба одновременно.
  
-<​code>​+<​code ​javascript>
 interface IAnimal { interface IAnimal {
   id: string;   id: string;
Строка 152: Строка 152:
 Класс, реализующий интерфейс,​ принадлежит к типу этого интерфейса. Класс, унаследованный от класса,​ реализующего интерфейс,​ также наследует принадлежность к реализуемым им интерфейсам. В подобных сценариях говорят,​ что класс наследует интерфейс. Класс, реализующий интерфейс,​ принадлежит к типу этого интерфейса. Класс, унаследованный от класса,​ реализующего интерфейс,​ также наследует принадлежность к реализуемым им интерфейсам. В подобных сценариях говорят,​ что класс наследует интерфейс.
  
-<​code>​+<​code ​javascript>
 interface IAnimal {} interface IAnimal {}
  
Строка 165: Строка 165:
 Класс, реализующий множество интерфейсов,​ принадлежит к типу каждого из них. Когда экземпляр класса,​ реализующего интерфейс,​ присваивают ссылке с типом интерфейса,​ то говорят,​ что экземпляр был ограничен типом интерфейса. То есть, функционал экземпляра класса урезается до описанного в интерфейсе (подробнее об этом речь пойдет в главе [[.|Совместимость объектов]]) и [[.|Совместимость функций]]). Класс, реализующий множество интерфейсов,​ принадлежит к типу каждого из них. Когда экземпляр класса,​ реализующего интерфейс,​ присваивают ссылке с типом интерфейса,​ то говорят,​ что экземпляр был ограничен типом интерфейса. То есть, функционал экземпляра класса урезается до описанного в интерфейсе (подробнее об этом речь пойдет в главе [[.|Совместимость объектов]]) и [[.|Совместимость функций]]).
  
-<​code>​+<​code ​javascript>
 interface IAnimal { interface IAnimal {
   name: string;   name: string;
Строка 196: Строка 196:
 Если множество логически связанных интерфейсов требуется объединить в один тип, то нужно воспользоваться механизмом расширения интерфейсов. Наследование интерфейсов осуществляется с помощью ключевого слова ''​extends'',​ после которого через запятую идет один или несколько идентификаторов расширяемых интерфейсов. Если множество логически связанных интерфейсов требуется объединить в один тип, то нужно воспользоваться механизмом расширения интерфейсов. Наследование интерфейсов осуществляется с помощью ключевого слова ''​extends'',​ после которого через запятую идет один или несколько идентификаторов расширяемых интерфейсов.
  
-<​code>​+<​code ​javascript>
 interface IIdentifiable {} interface IIdentifiable {}
 interface ILiving {} interface ILiving {}
Строка 209: Строка 209:
 Для примера представьте приложение,​ которое только выводит в консоль информацию о животных. Так как над объектом ''​Animal''​ будет выполняться только одна операция,​ то можно не бояться разгневать богов объектно-ориентированного проектирования и включить все нужные характеристики прямо в интерфейс ''​IAnimal''​. Для примера представьте приложение,​ которое только выводит в консоль информацию о животных. Так как над объектом ''​Animal''​ будет выполняться только одна операция,​ то можно не бояться разгневать богов объектно-ориентированного проектирования и включить все нужные характеристики прямо в интерфейс ''​IAnimal''​.
  
-<​code>​+<​code ​javascript>
 interface IAnimal { interface IAnimal {
   id: string;   id: string;
Строка 244: Строка 244:
 Но если переписать программу,​ чтобы она выполняла несколько не связанных логически операций над одним типом, в данном случае ''​IAnimal'',​ то ситуация изменится на противоположную. Но если переписать программу,​ чтобы она выполняла несколько не связанных логически операций над одним типом, в данном случае ''​IAnimal'',​ то ситуация изменится на противоположную.
  
-<​code>​+<​code ​javascript>
 interface IAnimal { interface IAnimal {
   /*...*/   /*...*/
Строка 276: Строка 276:
 В этом случае программа нарушает принцип ISP, так как статические методы ''​printId''​ и ''​printAge''​ получили доступ к данным,​ которые им не требуются для успешного выполнения. Это может привести к намеренной или случайной порче данных. В этом случае программа нарушает принцип ISP, так как статические методы ''​printId''​ и ''​printAge''​ получили доступ к данным,​ которые им не требуются для успешного выполнения. Это может привести к намеренной или случайной порче данных.
  
-<​code>​+<​code ​javascript>
 class AnimalUtil { class AnimalUtil {
   public static printId(animal:​ IAnimal): void {   public static printId(animal:​ IAnimal): void {
Строка 294: Строка 294:
 Поэтому в подобных ситуациях настоятельно рекомендуется “дробить” типы интерфейсов на меньшие составляющие и затем ограничивать им доступ к данным. Поэтому в подобных ситуациях настоятельно рекомендуется “дробить” типы интерфейсов на меньшие составляющие и затем ограничивать им доступ к данным.
  
-<​code>​+<​code ​javascript>
 interface IIdentifiable {} interface IIdentifiable {}
 interface ILiving {} interface ILiving {}
Строка 335: Строка 335:
 Когда интерфейс расширяет класс, он наследует описание членов,​ но не их реализацию. Когда интерфейс расширяет класс, он наследует описание членов,​ но не их реализацию.
  
-<​code>​+<​code ​javascript>
 class Animal { class Animal {
   nickname: string;   nickname: string;
Строка 355: Строка 355:
 Интерфейс,​ полученный путем расширения типа класса,​ может быть реализован только самим этим классом или его потомками,​ поскольку помимо публичных (''​public''​) также наследует закрытые (''​private''​) и защищенные (''​protected''​) члены. Интерфейс,​ полученный путем расширения типа класса,​ может быть реализован только самим этим классом или его потомками,​ поскольку помимо публичных (''​public''​) также наследует закрытые (''​private''​) и защищенные (''​protected''​) члены.
  
-<​code>​+<​code ​javascript>
 class Animal { class Animal {
   private uid: string;   private uid: string;
Строка 388: Строка 388:
 Конструктор указывается с помощью ключевого слова ''​new'',​ затем открываются фигурные скобки,​ в которых при наличии указываются параметры,​ а в конце указывается тип возвращаемого значения. Конструктор указывается с помощью ключевого слова ''​new'',​ затем открываются фигурные скобки,​ в которых при наличии указываются параметры,​ а в конце указывается тип возвращаемого значения.
  
-<​code>​+<​code ​javascript>
 new(p1: type, p2: type): type; new(p1: type, p2: type): type;
 </​code>​ </​code>​
Строка 394: Строка 394:
 Статические члены описываются так же, как и члены экземпляра. Статические члены описываются так же, как и члены экземпляра.
  
-<​code>​+<​code ​javascript>
 interface IAnimal { interface IAnimal {
   nickname: string;   nickname: string;
Строка 443: Строка 443:
 Помимо экземпляров и самих классов,​ интерфейсы могут описывать функциональные выражения. Это очень удобно,​ когда функциональный тип имеет большую сигнатуру,​ которая делает код менее читабельным. Помимо экземпляров и самих классов,​ интерфейсы могут описывать функциональные выражения. Это очень удобно,​ когда функциональный тип имеет большую сигнатуру,​ которая делает код менее читабельным.
  
-<​code>​+<​code ​javascript>
 // reduce(callbackfn:​ (previousValue:​ T, currentValue:​ T, currentIndex:​ number, array: T[]) => T, initialValue?:​ T): T; // reduce(callbackfn:​ (previousValue:​ T, currentValue:​ T, currentIndex:​ number, array: T[]) => T, initialValue?:​ T): T;
 var callback: ( var callback: (
Строка 455: Строка 455:
 В большинстве подобных случаев можно прибегнуть к помощи вывода типов. В большинстве подобных случаев можно прибегнуть к помощи вывода типов.
  
-<​code>​+<​code ​javascript>
 // reduce(callbackfn:​ (previousValue:​ T, currentValue:​ T, currentIndex:​ number, array: T[]) => T, initialValue?:​ T): T; // reduce(callbackfn:​ (previousValue:​ T, currentValue:​ T, currentIndex:​ number, array: T[]) => T, initialValue?:​ T): T;
  
Строка 478: Строка 478:
 Но в случае,​ если функциональное выражение является параметром функции,​ как, например,​ метод массива ''​reduce'',​ то решением может служить только явная декларация типа. Но в случае,​ если функциональное выражение является параметром функции,​ как, например,​ метод массива ''​reduce'',​ то решением может служить только явная декларация типа.
  
-<​code>​+<​code ​javascript>
 class Collection<​T>​ { class Collection<​T>​ {
   reduce(   reduce(
Строка 498: Строка 498:
 Для этого необходимо в теле интерфейса описать сигнатуру функции без указания идентификатора. Для этого необходимо в теле интерфейса описать сигнатуру функции без указания идентификатора.
  
-<​code>​+<​code ​javascript>
 interface ISumAll { interface ISumAll {
   (...valueAll:​ number[]): number;   (...valueAll:​ number[]): number;
Строка 515: Строка 515:
 Индексные члены подробно будут рассматриваться в главе [[.|Объектные типы с индексными членами (объектный тип с динамическими ключами)]],​ но не будет лишним и здесь коснуться этого механизма. Индексные члены подробно будут рассматриваться в главе [[.|Объектные типы с индексными членами (объектный тип с динамическими ключами)]],​ но не будет лишним и здесь коснуться этого механизма.
  
-<​code>​+<​code ​javascript>
 interface IIndentifier { interface IIndentifier {
   [BindingIdentifier:​ string]: Type;   [BindingIdentifier:​ string]: Type;
Строка 528: Строка 528:
 Различие между ними заключается в том, что второй обладает только телом и объявляется прямо в аннотации типа. Различие между ними заключается в том, что второй обладает только телом и объявляется прямо в аннотации типа.
  
-<​code>​+<​code ​javascript>
 let identifier: { p1: type; p2: type }; let identifier: { p1: type; p2: type };
 </​code>​ </​code>​
Строка 534: Строка 534:
 Интерфейс,​ объявленный с помощью ключевого слова ''​interface'',​ считается идентичным инлайн интерфейсу,​ если их описание совпадает. Но стоит обратить внимание,​ что это возможно благодаря структурной типизации,​ которая рассматривается в главе [[.|Совместимость типов на основе вида типизации]]. Интерфейс,​ объявленный с помощью ключевого слова ''​interface'',​ считается идентичным инлайн интерфейсу,​ если их описание совпадает. Но стоит обратить внимание,​ что это возможно благодаря структурной типизации,​ которая рассматривается в главе [[.|Совместимость типов на основе вида типизации]].
  
-<​code>​+<​code ​javascript>
 interface IAnimal { interface IAnimal {
   nickname: string;   nickname: string;
Строка 552: Строка 552:
 Как было сказано ранее, инлайн интерфейс можно объявлять в тех местах,​ в которых допускается указание типа. Тем не менее реализовывать (''​implements''​) и расширять (''​extends''​) инлайн интерфейс нельзя. Как было сказано ранее, инлайн интерфейс можно объявлять в тех местах,​ в которых допускается указание типа. Тем не менее реализовывать (''​implements''​) и расширять (''​extends''​) инлайн интерфейс нельзя.
  
-<​code>​+<​code ​javascript>
 interface IT1 {} interface IT1 {}
 interface IT2 {} interface IT2 {}
Строка 571: Строка 571:
 В случае,​ если в одной области видимости объявлено несколько одноимённых интерфейсов,​ то они будут объединены в один. В случае,​ если в одной области видимости объявлено несколько одноимённых интерфейсов,​ то они будут объединены в один.
  
-<​code>​+<​code ​javascript>
 // так видят разработчики // так видят разработчики
 interface IAnimal { interface IAnimal {
Строка 597: Строка 597:
 При попытке переопределить тип поля возникнет ошибка. При попытке переопределить тип поля возникнет ошибка.
  
-<​code>​+<​code ​javascript>
 interface IAnimal { interface IAnimal {
   name: string;   name: string;
Строка 611: Строка 611:
 Если в нескольких одноимённых интерфейсах будут описаны одноимённые методы с разными сигнатурами,​ то они будут расценены,​ как описание перегрузки. К тому же, интерфейсы,​ которые описывают множество одноимённых методов,​ сохраняют свой внутренний порядок. Если в нескольких одноимённых интерфейсах будут описаны одноимённые методы с разными сигнатурами,​ то они будут расценены,​ как описание перегрузки. К тому же, интерфейсы,​ которые описывают множество одноимённых методов,​ сохраняют свой внутренний порядок.
  
-<​code>​+<​code ​javascript>
 interface IBird {} interface IBird {}
 interface IFish {} interface IFish {}
Строка 648: Строка 648:
 Исключением из этого правила являются сигнатуры,​ которые имеют в своем описании литеральные строковые типы данных (''​literal String Types''​). Дело в том, что сигнатуры,​ содержащие в своем описании литеральные строковые типы, всегда размещаются перед сигнатурами,​ у которых нет в описании литеральных строковых типов. Исключением из этого правила являются сигнатуры,​ которые имеют в своем описании литеральные строковые типы данных (''​literal String Types''​). Дело в том, что сигнатуры,​ содержащие в своем описании литеральные строковые типы, всегда размещаются перед сигнатурами,​ у которых нет в описании литеральных строковых типов.
  
-<​code>​+<​code ​javascript>
 interface IBird {} interface IBird {}
 interface IFish {} interface IFish {}
typescript/types/interface.1675014490.txt.gz · Последние изменения: 2023/01/29 20:48 — werwolf