Me gustaría saber qué tienen en común el hombre y el niño y en qué se diferencian.
class Person {
name: string;
age: number;
}
class child extends Person {}
class man implements Person {}
Me gustaría saber qué tienen en común el hombre y el niño y en qué se diferencian.
class Person {
name: string;
age: number;
}
class child extends Person {}
class man implements Person {}
Respuestas:
extends
medio:La nueva clase es un niño . Obtiene beneficios que vienen con la herencia. Tiene todas las propiedades, métodos como padre. Puede anular algunos de estos e implementar nuevos, pero el material principal ya está incluido.
implements
medio:La nueva clase puede tratarse como la misma "forma" , mientras que no es un niño . Se podría pasar a cualquier método donde Person
se requiera, independientemente de tener un padre diferente alPerson
En OOP (lenguajes como C #, Java) usaríamos
extends
para beneficiarse de la herencia (ver wiki ). Pequeña cita:
... La herencia en la mayoría de los lenguajes orientados a objetos basados en clases es un mecanismo en el que un objeto adquiere todas las propiedades y comportamientos del objeto padre. La herencia permite a los programadores: crear clases que se basan en clases existentes ...
implements
será más por polimorfismo (ver wiki ). Pequeña cita:
... el polimorfismo es la provisión de una única interfaz a entidades de diferentes tipos ...
Entonces, podemos tener un árbol de herencia realmente diferente de nuestro class Man
.
class Man extends Human ...
pero si también declaramos que podemos pretender ser de un tipo diferente - Person
:
class Man extends Human
implements Person ...
.. entonces podemos usarlo en cualquier lugar, donde Person
sea necesario. Solo tenemos que cumplir con Persons "interface"
(es decir, implementar todas sus cosas públicas) .
implement
otra clase? Eso es realmente genialLa cara agradable de Javascript (uno de los beneficios) es el soporte integrado de la escritura Duck ( ver wiki ). Pequeña cita:
"Si camina como un pato y grazna como un pato, entonces debe ser un pato".
Entonces, en Javascript, si dos objetos diferentes ... tuvieran un método similar (por ejemplo render()
), se pueden pasar a una función que lo espera:
function(engine){
engine.render() // any type implementing render() can be passed
}
Para no perder eso, podemos hacer lo mismo en TypeScript, con más soporte mecanografiado. Y ahí es donde
class implements class
tiene su papel, donde tiene sentido
En lenguajes de programación orientada a objetos como C#
... no hay forma de hacer eso ...
Interfaces que amplían clases
Cuando un tipo de interfaz extiende un tipo de clase, hereda los miembros de la clase pero no sus implementaciones. Es como si la interfaz hubiera declarado a todos los miembros de la clase sin proporcionar una implementación. Las interfaces heredan incluso los miembros privados y protegidos de una clase base. Esto significa que cuando crea una interfaz que extiende una clase con miembros privados o protegidos, ese tipo de interfaz solo puede ser implementado por esa clase o una subclase de ella.
Esto es útil cuando tiene una jerarquía de herencia grande, pero desea especificar que su código funciona solo con subclases que tienen ciertas propiedades. Las subclases no tienen que estar relacionadas además de heredar de la clase base. Por ejemplo:
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 { }
Entonces, mientras
extends
significa - obtiene todo de su padreimplements
en este caso es casi como implementar una interfaz. El objeto hijo puede fingir que es padre ... pero no obtiene ninguna implementaciónextends
-tiene todo de su padre", ¿se aplica a los miembros privados? Por ejemplo, class Person {private name: string} class man extends Person{gender: string;}
¿ man
tiene el nombre de la propiedad?
En mecanografiado (y algunos otros lenguajes OO) tienes clases e interfaces.
Una interfaz no tiene implementación, es solo un "contrato" de los miembros / método que tiene este tipo.
Por ejemplo:
interface Point {
x: number;
y: number;
distance(other: Point): number;
}
Las instancias que implementan esta Point
interfaz deben tener dos miembros de tipo número: x
y y
, y un método distance
que recibe otra Point
instancia y devuelve un number
.
La interfaz no implementa ninguno de esos.
Las clases son las implementaciones:
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));
}
}
( código en el patio de recreo )
En su ejemplo, trata su Person
clase una vez como una clase cuando la extiende y una vez como una interfaz cuando la implementa.
Tu codigo:
class Person {
name: string;
age: number;
}
class Child extends Person {}
class Man implements Person {}
Tiene un error de compilación que dice:
La clase 'Man' implementa incorrectamente la interfaz 'Person'.
Falta la propiedad 'nombre' en el tipo 'Hombre'.
Y eso se debe a que las interfaces carecen de implementación.
Entonces, si eres implement
una clase, solo tomas su "contrato" sin la implementación, por lo que deberás hacer esto:
class NoErrorMan implements Person {
name: string;
age: number;
}
( código en el patio de recreo )
La conclusión es que en la mayoría de los casos desea extend
otra clase y no a implement
ella.
¡Gran respuesta de @ nitzan-tomer! Me ayudó mucho ... Amplié un poco su demo con:
IPoint interface;
Point implements IPoint;
Point3D extends Point;
Y cómo se comportan en funciones que esperan un IPoint
tipo.
Entonces, lo que he aprendido hasta ahora y lo he estado usando como regla general: si está usando clases y métodos que esperan tipos genéricos, use interfaces como los tipos esperados. Y asegúrese de que el padre o la clase base use esa interfaz. De esa manera, puede usar todas las subclases en la medida en que implementan la interfaz.
Aquí la demo extendida
extends
centrarse en heredar y implements
centrarse en la restricción, ya sean interfaces o clases.
extends
: La clase secundaria (que se extiende) heredará todas las propiedades y métodos de la clase se extiendeimplements
: La clase que usa la implements
palabra clave deberá implementar todas las propiedades y métodos de la clase queimplements
Para decirlo en términos más simples:
extends
: Aquí obtiene todos estos métodos / propiedades de la clase principal para que no tenga que implementar esto usted mismoimplements
: Aquí hay un contrato que la clase debe cumplir. La clase tiene que implementar al menos los siguientes métodos / propiedadesclass 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)
En el ejemplo podemos observar que la clase hija hereda todo de Person mientras que la clase man tiene que implementar todo de Person.
Si elimináramos algo de la clase man, por ejemplo, el método walk, obtendríamos el siguiente error de tiempo de compilación :
La clase 'man' implementa incorrectamente la clase 'Person'. ¿Querías extender 'Persona' y heredar sus miembros como una subclase? Falta la propiedad 'caminar' en el tipo 'hombre' pero es obligatoria en el tipo 'Persona'. (2720)