Я хотел бы знать, что у man и child есть и как они отличаются.
class Person {
name: string;
age: number;
}
child extends Person {}
man implements Person{}
Я хотел бы знать, что у man и child есть и как они отличаются.
class Person {
name: string;
age: number;
}
child extends Person {}
man implements Person{}
Документация должна помочь здесь:
Интерфейсы, расширяющие классы
Когда тип интерфейса расширяет тип класса, он наследует членов класса, но не их реализации. Это как если бы интерфейс объявили всех членов класса, не предоставив реализация. Интерфейсы наследуют даже частные и защищенные членов базового класса. Это означает, что при создании интерфейса который расширяет класс с частными или защищенными членами, этот интерфейс тип может быть реализован только этим классом или подклассом.
Это полезно, если у вас есть большая иерархия наследования, но вы хотите указать, что ваш код работает только с подклассами, которые имеют определенные свойства. Подклассы не должны быть связаны помимо наследования из базового класса. Например:
class Control { private state: any; } interface SelectableControl extends Control { select(): void; } class Button extends Control { select() { } } class TextBox extends Control { select() { } } class Image extends Control { } class Location { select() { } }
Итак, пока
extends
означает - он получает все из своего родителяimplements
в этом случае почти как реализация интерфейса. Детский объект может притворяться, что он является родителем.. но он не получает никакой реализации.В typescript (и некоторых других языках OO) у вас есть классы и интерфейсы.
Интерфейс не имеет реализации, это всего лишь "контракт" того, какие члены/метод имеет этот тип.
Например:
interface Point {
x: number;
y: number;
distance(other: Point): number;
}
Экземпляры, которые реализуют этот интерфейс Point
, должны иметь два члена типа: x
и y
, а один метод distance
, который получает другой экземпляр Point
и возвращает number
.
Интерфейс не реализует ни одного из них.
Классы - это реализации:
class PointImplementation implements Point {
public x: number;
public y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
public distance(other: Point): number {
return Math.sqrt(Math.pow(this.x - other.x, 2) + Math.pow(this.y - other.y, 2));
}
}
В вашем примере вы относитесь к классу Person
один раз как к классу при его расширении и один раз в качестве интерфейса при его реализации.
Ваш код:
class Person {
name: string;
age: number;
}
class Child extends Person {}
class Man implements Person {}
Имеет ошибку компиляции:
Класс "Человек" неправильно реализует интерфейс "Человек" .
Свойство "имя" отсутствует в типе "Человек" .
И это потому, что интерфейсам не хватает реализации.
Поэтому, если вы implement
класс, тогда вы выполняете свой "контракт" без реализации, поэтому вам нужно будет сделать это:
class NoErrorMan implements Person {
name: string;
age: number;
}
Нижняя строка состоит в том, что в большинстве случаев вы хотите extend
другой класс, а не implement
его.
Отличный ответ от @nitzan-tomer! Помог мне много... Я немного расширил свою демонстрацию:
IPoint interface;
Point implements IPoint;
Point3D extends Point;
И как они ведут себя в функциях, ожидающих тип IPoint.
Итак, что я узнал до сих пор и использовал в качестве правила большого пальца: если вы используете классы и методы, ожидающие общие типы, используйте интерфейсы как ожидаемые типы. И убедитесь, что родительский или базовый класс использует этот интерфейс. Таким образом, вы можете использовать все подклассы в тех, которые реализуют интерфейс.
Предыдущая расширенная демонстрация