Хотелось бы узнать, что общего у мужчины и ребенка и чем они отличаются.
class Person {
name: string;
age: number;
}
class child extends Person {}
class man implements Person {}
Хотелось бы узнать, что общего у мужчины и ребенка и чем они отличаются.
class Person {
name: string;
age: number;
}
class child extends Person {}
class man implements Person {}
Ответы:
extends
средства:Новый класс является ребенком . Он получает выгоду от наследования. Он имеет все свойства и методы в качестве своего родителя. Он может переопределить некоторые из них и реализовать новые, но родительский материал уже включен.
implements
средства:Новый класс можно рассматривать как же «формы» , в то время как это не ребенок . Его можно передать любому методу, где Person
требуется, независимо от того, имеет ли родительский элемент, отличный отPerson
В ООП (такие языки, как C #, Java) мы бы использовали
extends
получать прибыль от наследства (см. вики ). Небольшой цитата:
... Наследование в большинстве объектно-ориентированных языков на основе классов - это механизм, в котором один объект получает все свойства и поведение родительского объекта. Наследование позволяет программистам: создавать классы, основанные на существующих классах ...
implements
будет больше для полиморфизма (см. вики ). Небольшой цитата:
... полиморфизм - это предоставление единого интерфейса для сущностей разных типов ...
Итак, у нас может быть действительно другое дерево наследования class Man
.
class Man extends Human ...
но если мы также заявим, что можем притвориться другим типом - Person
:
class Man extends Human
implements Person ...
.. тогда мы можем использовать его где угодно, где Person
это необходимо. Нам просто нужно выполнить Persons "interface"
(т.е. реализовать все его публичные вещи) .
implement
другой класс? Это действительно крутоКрасивое лицо Javascript (одно из преимуществ) - это встроенная поддержка Duck typing ( см. Вики ). Небольшой цитата:
«Если он ходит как утка и крякает как утка, значит, это должна быть утка».
Итак, в Javascript, если два разных объекта ... будут иметь один похожий метод (например render()
), они могут быть переданы функции, которая его ожидает:
function(engine){
engine.render() // any type implementing render() can be passed
}
Чтобы не потерять это - мы можем в Typescript сделать то же самое - с более типизированной поддержкой. И вот где
class implements class
имеет свою роль там, где это имеет смысл
В языках ООП, как C#
... нет способа сделать это ...
Интерфейсы, расширяющие классы
Когда тип интерфейса расширяет тип класса, он наследует члены класса, но не их реализации. Это как если бы интерфейс объявил всех членов класса без предоставления реализации. Интерфейсы наследуют даже частные и защищенные члены базового класса. Это означает, что когда вы создаете интерфейс, который расширяет класс частными или защищенными членами, этот тип интерфейса может быть реализован только этим классом или его подклассом.
Это полезно, когда у вас есть большая иерархия наследования, но вы хотите указать, что ваш код работает только с подклассами, имеющими определенные свойства. Подклассы не должны быть связаны, кроме наследования от базового класса. Например:
class Control { private state: any; } interface SelectableControl extends Control { select(): void; } class Button extends Control implements SelectableControl { select() { } } class TextBox extends Control { select() { } } // Error: Property 'state' is missing in type 'Image'. class Image implements SelectableControl { private state: any; select() { } } class Location { }
Так что пока
extends
означает - он получает все от своего родителяimplements
в этом случае почти как реализация интерфейса. Дочерний объект может притвориться родительским ... но не получает никакой реализацииextends
- он получает все от своего родителя", применяется ли это к закрытым членам? Например class Person {private name: string} class man extends Person{gender: string;}
, man
есть название свойства?
В машинописном тексте (и некоторых других объектно-ориентированных языках) у вас есть классы и интерфейсы.
Интерфейс не имеет реализации, это просто «договор» о том, какие члены / метод имеет этот тип.
Например:
interface Point {
x: number;
y: number;
distance(other: Point): number;
}
Экземпляры, реализующие этот Point
интерфейс, должны иметь два члена типа number: 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 {}
Имеется ошибка компиляции:
Класс Man неправильно реализует интерфейс Person.
В типе Man отсутствует свойство name.
И это потому, что интерфейсам не хватает реализации.
Итак, если вы implement
класс, вы берете только его «контракт» без реализации, поэтому вам нужно сделать это:
class NoErrorMan implements Person {
name: string;
age: number;
}
Суть в том, что в большинстве случаев вам нужен extend
другой класс, а не implement
он.
Отличный ответ от @ nitzan-tomer! Мне очень помогло ... Я немного расширил его демо:
IPoint interface;
Point implements IPoint;
Point3D extends Point;
И как они ведут себя в функциях, ожидающих IPoint
тип.
Итак, то, что я изучил до сих пор и использовал как практическое правило: если вы используете классы и методы, ожидающие универсальных типов, используйте интерфейсы как ожидаемые типы. И убедитесь, что родительский или базовый класс использует этот интерфейс. Таким образом, вы можете использовать все подклассы в той мере, в какой они реализуют интерфейс.
extends
сосредоточиться на наследовании и implements
сосредоточиться на ограничениях, будь то интерфейсы или классы.
extends
: Дочерний класс (который расширяется) наследует все свойства и методы класса, который расширяется.implements
: Класс, который использует implements
ключевое слово, должен будет реализовать все свойства и методы класса, который онimplements
Проще говоря:
extends
: Здесь вы получаете все эти методы / свойства из родительского класса, поэтому вам не нужно реализовывать это самостоятельноimplements
: Вот договор, которому должен следовать класс. Класс должен реализовывать как минимум следующие методы / свойстваclass Person {
name: string;
age: number;
walk(): void {
console.log('Walking (person Class)')
}
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
class child extends Person { }
// Man has to implements at least all the properties
// and methods of the Person class
class man implements Person {
name: string;
age: number
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
walk(): void {
console.log('Walking (man class)')
}
}
(new child('Mike', 12)).walk();
// logs: Walking(person Class)
(new man('Tom', 12)).walk();
// logs: Walking(man class)
В этом примере мы можем заметить, что дочерний класс наследует все от Person, тогда как класс man должен реализовать все от самого Person.
Если бы мы удалили что-то из класса man, например метод walk, мы получили бы следующую ошибку времени компиляции :
Класс man неправильно реализует класс Person. Вы хотели расширить "Person" и унаследовать его члены как подкласс? Свойство walk отсутствует в типе man, но требуется в типе Person. (2720)