В TypeScript с классами связано несколько неочевидных моментов. Неожиданная встреча с ними на практике непременно приведет к возникновению множества вопросов, ответы на которые содержит текущая глава.
Как уже можно было догадаться, при реализации классом другого класса действуют те же правила, что и при расширении класса интерфейсом. То есть класс, у которого все члены объявлены как публичные (public), может реализовать любой другой класс. Если класс имеет определение членов с модификаторами доступа private или protected, то его может реализовать только этот же класс или его потомки.
На текущий момент известно, что два интерфейса, объявленные в одной области видимости, сливаются вместе. Кроме этого, если интерфейс объявлен в одной области видимости с одноимённым классом, то компилятор считает, что класс реализовал этот интерфейс.
1 2 3 4 5 6 7 8 9101112131415
interfaceAnimal{id:string;age:number;}classAnimal{}constanimal=newAnimal();// Okanimal.id='animal';// Okanimal.age=0;// Okconst{id,age}=animal;// Ok -> id: string and age: numberconsole.log(id,age);// 'animal', 0
Переопределение свойств полями и наоборот при наследовании¶
В JavaScript при использовании механизма наследования (extends) производный класс в состоянии переопределить свойство, объявленное в базовом классе полем и наоборот, поле свойством.
classBase{getvalue(){return'base';}setvalue(value){console.log(value);}}classDerivedextendsBase{value='derived';}letderived=newDerived();console.log(derived.value);// 'derived'derived.value=`new derived`;// несложно догадаться, что при присваивании нового значения console.log в сеттер базового класса вызвана не будетconsole.log(derived.value);// 'new derived'/** * То же справедливо и для переопределения * поля, объявленного в базовом классе свойствами * производного класса. */
Но во избежание казусов, сопряженных с этим поведением, TypeScript запрещает переопределения при наследовании.
1 2 3 4 5 6 7 8 91011121314151617
classBase{getvalue(){return'value';}setvalue(value:string){}}classDerivedextendsBase{/** * Error -> * * 'value' is defined as an accessor in class 'Base', * but is overridden here in 'Derived' * as an instance property. */value='value';}
1 2 3 4 5 6 7 8 91011121314151617
classBase{value='value';}classDerivedextendsBase{/** * Error -> * * 'value' is defined as a property in class 'Base', * but is overridden here in 'Derived' as an accessor. */getvalue(){return'value';}setvalue(value:string){}}