Я хотів би знати, що спільного між чоловіком і дитиною і чим вони відрізняються.
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
У OOP (такі мови, як C #, Java) ми б використовували
extendsотримати прибуток від спадщини (див. wiki ). Маленький цитат:
... Спадкування в більшості класових об'єктно-орієнтованих мов - це механізм, за допомогою якого один об'єкт набуває всіх властивостей і поведінки батьківського об'єкта. Спадщина дозволяє програмістам: створювати класи, побудовані на існуючих класах ...
implementsбуде більше для поліморфізму (див. wiki ). Маленький цитат:
... поліморфізм - це надання єдиного інтерфейсу суб'єктам різних типів ...
Отже, у нас може бути справді інше дерево спадкування class Man.
class Man extends Human ...
але якщо ми також заявляємо, що можемо претендувати на різний тип - Person:
class Man extends Human
implements Person ...
.. тоді ми можемо використовувати його де завгодно, де Personпотрібно. Ми просто повинні виконати персони "interface" (тобто реалізувати всі її публічні речі) .
implementінший клас? Це справді класні речіГарне обличчя Javascript (одна з переваг) - це вбудована підтримка введення качки ( див. Вікі ). Маленький цитат:
"Якщо вона ходить, як качка, і хитається, як качка, то це повинна бути качка".
Отже, у Javascript, якщо два різних об'єкти ... будуть мати один подібний метод (наприклад render()), вони можуть бути передані функції, яка очікує цього:
function(engine){
engine.render() // any type implementing render() can be passed
}
Щоб цього не втратити - ми можемо зробити і в Typescript те саме - з більш набраною підтримкою. І ось де
class implements class
має свою роль, де це має сенс
У мовах OOP як 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інтерфейс, повинні мати два члени типу типу: xі yта один метод, distanceякий отримує інший Pointекземпляр і повертає a 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'.
Властивості 'name' відсутнє в типі 'Man'.
І це тому, що в інтерфейсах бракує реалізації.
Тож якщо ви 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, тоді як клас людини повинен реалізовувати все від Person.
Якби ми видаляли щось із класу man, наприклад метод walk, ми отримали б таку помилку часу компіляції :
Клас 'man' неправильно реалізує клас 'Person'. Ви мали намір поширити "Особу" та успадкувати її членів як підклас? Властивість "прогулянка" відсутня в типі "людина", але вимагається в типі "людина" (2720)