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

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


typescript:oop:interfaces

Различия

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

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

typescript:oop:interfaces [2023/05/31 23:21]
werwolf создано
typescript:oop:interfaces [2023/05/31 23:22] (текущий)
werwolf
Строка 1: Строка 1:
-====== ​Interfaces¶ ​======+====== ​Interfaces ​======
  
 Несмотря на то, что тема, относящаяся к интерфейсам,​ очень проста,​ именно она вызывает наибольшее количество вопросов у начинающих разработчиков. Поэтому такие вопросы как для чего нужны интерфейсы,​ когда их применять,​ а когда нет, будут подробно рассмотрены в этой главе. Несмотря на то, что тема, относящаяся к интерфейсам,​ очень проста,​ именно она вызывает наибольшее количество вопросов у начинающих разработчиков. Поэтому такие вопросы как для чего нужны интерфейсы,​ когда их применять,​ а когда нет, будут подробно рассмотрены в этой главе.
  
-===== Общая теория¶ =====+===== Общая теория =====
  
 По факту интерфейс затрагивает сразу несколько аспектов создания программ,​ относящихся к проектированию,​ реализации,​ конечной сборке. Поэтому,​ чтобы понять предназначение интерфейса,​ необходимо рассмотреть каждый аспект по отдельности. По факту интерфейс затрагивает сразу несколько аспектов создания программ,​ относящихся к проектированию,​ реализации,​ конечной сборке. Поэтому,​ чтобы понять предназначение интерфейса,​ необходимо рассмотреть каждый аспект по отдельности.
Строка 23: Строка 23:
 С теорией закончено. Осталось подробно рассмотреть реализацию интерфейсов в TypeScript. С теорией закончено. Осталось подробно рассмотреть реализацию интерфейсов в TypeScript.
  
-===== Интерфейс в TypeScript¶ ​=====+===== Интерфейс в TypeScript ​=====
  
 TypeScript предлагает новый тип данных,​ определяемый с помощью синтаксической конструкции,​ называемой интерфейс (''​interface''​). TypeScript предлагает новый тип данных,​ определяемый с помощью синтаксической конструкции,​ называемой интерфейс (''​interface''​).
Строка 31: Строка 31:
 Класс, реализующий интерфейс,​ обязан реализовать все описанные в нём члены. Поэтому интерфейс является гарантией наличия описанных в нем характеристик у реализующего его объекта. Все члены, описанные в интерфейсе,​ неявно имеют модификатор доступа ''​public''​. Интерфейс предназначен для описания api или другими словами состояния и поведения,​ предназначенного для взаимодействия внешнего мира с объектом. Класс, реализующий интерфейс,​ обязан реализовать все описанные в нём члены. Поэтому интерфейс является гарантией наличия описанных в нем характеристик у реализующего его объекта. Все члены, описанные в интерфейсе,​ неявно имеют модификатор доступа ''​public''​. Интерфейс предназначен для описания api или другими словами состояния и поведения,​ предназначенного для взаимодействия внешнего мира с объектом.
  
-===== Объявление (declaration)¶ =====+===== Объявление (declaration) =====
  
 В TypeScript интерфейс объявляется с помощью ключевого слова ''​interface'',​ после которого указывается идентификатор (имя), за которым следует тело, заключенное в фигурные скобки,​ содержащее описание. В TypeScript интерфейс объявляется с помощью ключевого слова ''​interface'',​ после которого указывается идентификатор (имя), за которым следует тело, заключенное в фигурные скобки,​ содержащее описание.
  
-<​code>​+<​code ​javascript>
 interface Identifier { interface Identifier {
   // тело интерфейса   // тело интерфейса
Строка 43: Строка 43:
 Объявление интерфейса возможно как в контексте модуля,​ так и в контексте функции или метода. Объявление интерфейса возможно как в контексте модуля,​ так и в контексте функции или метода.
  
-<​code>​+<​code ​javascript>
 interface Identifier {} // контекст модуля interface Identifier {} // контекст модуля
  
Строка 57: Строка 57:
 </​code>​ </​code>​
  
-===== Конвенции именования интерфейсов¶ =====+===== Конвенции именования интерфейсов =====
  
 Прежде чем продолжить,​ нужно обратить внимание на такой аспект,​ как конвенции именования интерфейсов. Существует два вида именования. Прежде чем продолжить,​ нужно обратить внимание на такой аспект,​ как конвенции именования интерфейсов. Существует два вида именования.
Строка 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>​
Строка 75: Строка 75:
 Чтобы сразу расставить все точки над i, стоит заметить,​ что в дальнейшем идентификаторы интерфейсов будут указываться по конвенциям C#. Чтобы сразу расставить все точки над i, стоит заметить,​ что в дальнейшем идентификаторы интерфейсов будут указываться по конвенциям C#.
  
-===== Реализация интерфейса (implements)¶ =====+===== Реализация интерфейса (implements) =====
  
 Как уже было сказано в самом начале,​ все члены интерфейса являются открытыми (''​public''​),​ и их объявление не может содержать модификатор ''​static''​. Кроме того, в TypeScript интерфейсы не могут содержать реализацию. Как уже было сказано в самом начале,​ все члены интерфейса являются открытыми (''​public''​),​ и их объявление не может содержать модификатор ''​static''​. Кроме того, в TypeScript интерфейсы не могут содержать реализацию.
Строка 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 {}
Строка 117: Строка 117:
 </​code>​ </​code>​
  
-===== Декларация свойств get и set (accessors)¶ =====+===== Декларация свойств get и set (accessors) =====
  
 Несмотря на то, что в интерфейсе можно декларировать поля и методы,​ в нем нельзя декларировать свойства ''​get''​ и ''​set''​ (аксессоры). Но, несмотря на это, задекларированное в интерфейсе поле может быть совместимо не только с полем, но и аксессорами. При этом нет разницы,​ будет в объекте объявлен getter, setter или оба одновременно. Несмотря на то, что в интерфейсе можно декларировать поля и методы,​ в нем нельзя декларировать свойства ''​get''​ и ''​set''​ (аксессоры). Но, несмотря на это, задекларированное в интерфейсе поле может быть совместимо не только с полем, но и аксессорами. При этом нет разницы,​ будет в объекте объявлен getter, setter или оба одновременно.
  
-<​code>​+<​code ​javascript>
 interface IAnimal { interface IAnimal {
   id: string;   id: string;
Строка 148: Строка 148:
 </​code>​ </​code>​
  
-===== Указание интерфейса в качестве типа (interface types)¶ =====+===== Указание интерфейса в качестве типа (interface types) =====
  
 Класс, реализующий интерфейс,​ принадлежит к типу этого интерфейса. Класс, унаследованный от класса,​ реализующего интерфейс,​ также наследует принадлежность к реализуемым им интерфейсам. В подобных сценариях говорят,​ что класс наследует интерфейс. Класс, реализующий интерфейс,​ принадлежит к типу этого интерфейса. Класс, унаследованный от класса,​ реализующего интерфейс,​ также наследует принадлежность к реализуемым им интерфейсам. В подобных сценариях говорят,​ что класс наследует интерфейс.
  
-<​code>​+<​code ​javascript>
 interface IAnimal {} interface IAnimal {}
  
Строка 165: Строка 165:
 Класс, реализующий множество интерфейсов,​ принадлежит к типу каждого из них. Когда экземпляр класса,​ реализующего интерфейс,​ присваивают ссылке с типом интерфейса,​ то говорят,​ что экземпляр был ограничен типом интерфейса. То есть, функционал экземпляра класса урезается до описанного в интерфейсе (подробнее об этом речь пойдет в главе [[.|Совместимость объектов]]) и [[.|Совместимость функций]]). Класс, реализующий множество интерфейсов,​ принадлежит к типу каждого из них. Когда экземпляр класса,​ реализующего интерфейс,​ присваивают ссылке с типом интерфейса,​ то говорят,​ что экземпляр был ограничен типом интерфейса. То есть, функционал экземпляра класса урезается до описанного в интерфейсе (подробнее об этом речь пойдет в главе [[.|Совместимость объектов]]) и [[.|Совместимость функций]]).
  
-<​code>​+<​code ​javascript>
 interface IAnimal { interface IAnimal {
   name: string;   name: string;
Строка 192: Строка 192:
 Несмотря на то, что интерфейс является синтаксической конструкцией и может указываться в качестве типа, после компиляции от него не остается и следа. Это в свою очередь означает,​ что интерфейс,​ как тип данных,​ может использоваться только на этапе компиляции. Другими словами,​ компилятор сможет предупредить об ошибках несоответствия объекта описанному интерфейсу,​ но проверить на принадлежность к типу интерфейса с помощью операторов ''​typeof''​ или ''​instanceof''​ не получится,​ поскольку они выполняются во время выполнения программы. Но в TypeScript существует механизм (который будет рассмотрен далее в главе [[.|Защитники типа]]),​ позволяющий в некоторой мере решить эту проблему. Несмотря на то, что интерфейс является синтаксической конструкцией и может указываться в качестве типа, после компиляции от него не остается и следа. Это в свою очередь означает,​ что интерфейс,​ как тип данных,​ может использоваться только на этапе компиляции. Другими словами,​ компилятор сможет предупредить об ошибках несоответствия объекта описанному интерфейсу,​ но проверить на принадлежность к типу интерфейса с помощью операторов ''​typeof''​ или ''​instanceof''​ не получится,​ поскольку они выполняются во время выполнения программы. Но в TypeScript существует механизм (который будет рассмотрен далее в главе [[.|Защитники типа]]),​ позволяющий в некоторой мере решить эту проблему.
  
-===== Расширение интерфейсов (extends interface)¶ =====+===== Расширение интерфейсов (extends interface) =====
  
 Если множество логически связанных интерфейсов требуется объединить в один тип, то нужно воспользоваться механизмом расширения интерфейсов. Наследование интерфейсов осуществляется с помощью ключевого слова ''​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 {}
Строка 329: Строка 329:
 </​code>​ </​code>​
  
-===== Расширение интерфейсом класса (extends class)¶ =====+===== Расширение интерфейсом класса (extends class) =====
  
 В случаях,​ когда требуется создать интерфейс для уже имеющегося класса,​ нет необходимости тратить силы на перечисление членов класса в интерфейсе. В TypeScript интерфейсу достаточно расширить тип класса. В случаях,​ когда требуется создать интерфейс для уже имеющегося класса,​ нет необходимости тратить силы на перечисление членов класса в интерфейсе. В TypeScript интерфейсу достаточно расширить тип класса.
Строка 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;
Строка 380: Строка 380:
 </​code>​ </​code>​
  
-===== Описание класса (функции-конструктора)¶ =====+===== Описание класса (функции-конструктора) =====
  
 Известный факт, что в JavaScript, а, следовательно,​ и в TypeScript, конструкция ''​class''​ - это лишь “синтаксический сахар” над старой доброй функцией-конструктором. Эта особенность позволяет описывать интерфейсы не только для экземпляров класса,​ но и для самих классов (функций-конструкторов). Проще говоря,​ с помощью интерфейса можно описать как конструктор,​ так и статические члены класса,​ с одной оговоркой — этот интерфейс можно использовать только в качестве типа. То есть класс не может указывать реализацию такого интерфейса с помощью ключевого слова ''​implements'',​ сопряженную с экземпляром,​ а не самим классом. Известный факт, что в JavaScript, а, следовательно,​ и в TypeScript, конструкция ''​class''​ - это лишь “синтаксический сахар” над старой доброй функцией-конструктором. Эта особенность позволяет описывать интерфейсы не только для экземпляров класса,​ но и для самих классов (функций-конструкторов). Проще говоря,​ с помощью интерфейса можно описать как конструктор,​ так и статические члены класса,​ с одной оговоркой — этот интерфейс можно использовать только в качестве типа. То есть класс не может указывать реализацию такого интерфейса с помощью ключевого слова ''​implements'',​ сопряженную с экземпляром,​ а не самим классом.
Строка 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;
Строка 439: Строка 439:
 </​code>​ </​code>​
  
-===== Описание функционального выражения¶ =====+===== Описание функционального выражения =====
  
 Помимо экземпляров и самих классов,​ интерфейсы могут описывать функциональные выражения. Это очень удобно,​ когда функциональный тип имеет большую сигнатуру,​ которая делает код менее читабельным. Помимо экземпляров и самих классов,​ интерфейсы могут описывать функциональные выражения. Это очень удобно,​ когда функциональный тип имеет большую сигнатуру,​ которая делает код менее читабельным.
  
-<​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;
Строка 511: Строка 511:
 </​code>​ </​code>​
  
-===== Описание индексных членов в объектных типах¶ =====+===== Описание индексных членов в объектных типах =====
  
 Индексные члены подробно будут рассматриваться в главе [[.|Объектные типы с индексными членами (объектный тип с динамическими ключами)]],​ но не будет лишним и здесь коснуться этого механизма. Индексные члены подробно будут рассматриваться в главе [[.|Объектные типы с индексными членами (объектный тип с динамическими ключами)]],​ но не будет лишним и здесь коснуться этого механизма.
  
-<​code>​+<​code ​javascript>
 interface IIndentifier { interface IIndentifier {
   [BindingIdentifier:​ string]: Type;   [BindingIdentifier:​ string]: Type;
Строка 522: Строка 522:
 </​code>​ </​code>​
  
-===== Инлайн интерфейсы (Inline Interface)¶ =====+===== Инлайн интерфейсы (Inline Interface) =====
  
 Помимо описания объекта,​ в конструкции,​ объявляемой с помощью ключевого слова ''​interface'',​ тип объекта можно описать прямо в месте указания типа. Такой способ объявления типа неформально обозначается как инлайн интерфейс (inline interface). Всё ранее описанное для типов интерфейсов,​ объявленных с помощью ключевого слова ''​interface'',​ в полной мере верно и для их инлайн аналогов. Помимо описания объекта,​ в конструкции,​ объявляемой с помощью ключевого слова ''​interface'',​ тип объекта можно описать прямо в месте указания типа. Такой способ объявления типа неформально обозначается как инлайн интерфейс (inline interface). Всё ранее описанное для типов интерфейсов,​ объявленных с помощью ключевого слова ''​interface'',​ в полной мере верно и для их инлайн аналогов.
Строка 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 {}
Строка 567: Строка 567:
 Хотя последнее утверждение и не совсем верно. В дальнейшем будет рассказано о такой замечательной конструкции,​ как обобщения (глава [[.|Обобщения (Generics)]]),​ в которых,​ как раз таки возможно расширять (''​extends''​) инлайн интерфейсы. Хотя последнее утверждение и не совсем верно. В дальнейшем будет рассказано о такой замечательной конструкции,​ как обобщения (глава [[.|Обобщения (Generics)]]),​ в которых,​ как раз таки возможно расширять (''​extends''​) инлайн интерфейсы.
  
-===== Слияние интерфейсов¶ =====+===== Слияние интерфейсов =====
  
 В случае,​ если в одной области видимости объявлено несколько одноимённых интерфейсов,​ то они будут объединены в один. В случае,​ если в одной области видимости объявлено несколько одноимённых интерфейсов,​ то они будут объединены в один.
  
-<​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/oop/interfaces.1685564472.txt.gz · Последние изменения: 2023/05/31 23:21 — werwolf