Interface et classe en TypeScript
dans C# il y a une énorme différence entre les interfaces et les classes. En effet, une classe représente un type de référence, de sorte que nous pouvons réellement créer des objets modelés sur cette classe, tandis que les interfaces sont destinées à être des contrats qu'une classe signe pour assurer l'existence d'un certain comportement. En particulier, nous ne pouvons pas créer d'instances d'interfaces.
le point entier avec les interfaces est d'exposer le comportement. Une classe l'implémente en donnant une implémentation explicite de dit comportement.
Dans ce cas, bien que les interfaces contiennent des propriétés, la plupart du temps nous nous soucions des interfaces en raison de problèmes de comportement. Donc la plupart des interfaces de ce type ne sont que des contrats de comportement.
a la typographie, d'un autre côté, j'ai l'air quelque chose qui m'a mis assez mal à l'aise, et en vérité j'ai vu cela plus d'une fois, ce qui est la raison de cette question.
Dans un tutoriel que j'ai vu ceci:
export interface User {
name: string; // required with minimum 5 chracters
address?: {
street?: string; // required
postcode?: string;
}
}
Mais attendez une minute. Pourquoi User
est une interface? Si nous pensons comme C#, User
ne devrait pas être une interface. En vérité, en le regardant, il semble que nous définissons le type de données User
, au lieu d'un contrat de comportement.
Penser comme nous le faisons en C#, la chose naturelle serait ceci:
export class User {
public name: string;
public address: Address;
}
export class Address {
public street: string;
public postcode: string;
}
mais cette chose d'utiliser des interfaces comme nous le faisons avec des classes, pour définir juste un type de données, plutôt que de définir un contrat de comportement, semble très commun en écriture dactylographiée.
alors, quelles interfaces sont prévues en écriture typographique? Pourquoi les gens utilisent-ils des interfaces en TypeScript comme nous utilisons des clases en C#? Comment les interfaces devraient-elles être correctement utilisées dans TypeScript: pour établir des contrats de comportement, ou pour définir les propriétés et les objets devraient avoir?
5 réponses
considérez Qu'en Javascript, les données sont souvent échangées comme des objets simples, souvent par L'intermédiaire de JSON:
let data = JSON.parse(someString);
disons que cette data
est un tableau de User
les objets, et nous allons passer à une fonction:
data.forEach(user => foo(user))
foo
serait tapé comme ceci:
function foo(user: User) { ... }
Mais attendez, à aucun moment, nous n' new User
! Devrions-nous? Devrait-on avoir à écrire un cours User
et map
tous les data
pour elle, même si le résultat serait exactement le même, un Object
avec des propriétés? Non, ce serait de la folie juste pour satisfaire le système de type, mais ne pas changer quoi que ce soit sur le runtime. A simple interface
qui décrit comment l'objet spécifique est censé ressembler (se" comporter") est parfaitement suffisant ici.
Alors, quelles interfaces sont prévues en écriture typographique?
Le Fichier D'Enregistrement Manuel semble dire que les interfaces sont conçus pour "la définition des contrats dans votre code".
pourquoi les gens utilisent-ils des interfaces en caractères typographiques comme nous utilisons des classes en C#?
John Papa s'étend sur le sujet des classes et des interfaces sur son blog. Il suggère que les classes sont les mieux adaptées pour "créer plusieurs nouvelles instances, en utilisant l'héritage, [et] les objets singleton". Ainsi, sur la base de l'intention des interfaces dactylographiées comme décrit dans le manuel dactylographique et de l'opinion d'un homme, il semblerait que les classes ne sont pas nécessaires pour établir des contrats en Dactylographie. Vous devriez plutôt utiliser des interfaces. Vos sens seront encore offensés.)
les Interfaces devraient être correctement utilisées en Dactylographie: pour établir des contrats de comportement, ou pour définir les propriétés et l'objet devrait avoir?
si je comprends la question, vous demandez si les interfaces devraient établir contrats de comportement ou contrats de structure. Pour cela, je répondrais: les deux. Les interfaces dactylographiées peuvent encore être utilisées de la même manière que les interfaces en C# ou en Java (c'est-à-dire pour décrire le comportement d'une classe), mais elles offrent aussi la possibilité de décrire la structure des données.
de plus, mon collaborateur m'a harcelé pour avoir utilisé des classes au lieu d'interfaces parce que les interfaces ne produisent pas de code dans le compilateur.
Exemple:
Ce Texte Dactylographié:
class Car implements ICar {
foo: string;
bar(): void {
}
}
interface ICar {
foo: string;
bar(): void;
}
produit ce Javascript:
var Car = (function () {
function Car() {
}
Car.prototype.bar = function () {
};
return Car;
}());
les Interfaces en typescript sont similaires aux interfaces en C# en ce qu'elles fournissent toutes deux un contrat. Cependant opposé à C # interfaces qui ne contiennent que des méthodes les interfaces dactylographiées peuvent aussi décrire des champs ou des propriétés que les objets contiennent. Par conséquent, ils peuvent également être utilisés pour des choses qui ne sont pas directement possibles avec les interfaces C#.
une différence majeure entre les interfaces et les classes dans typescript est que les interfaces n'ont pas de représentation runtime et il n'y aura pas de le code émis pour eux. Les Interfaces sont très largement utilisables. Par exemple, vous pouvez utiliser des objets littéraux pour construire des objets avec satisfy une interface. Comme:
let user: User = {
name: 'abc',
address: {
street: 'xyz',
},
};
ou vous pouvez assigner n'importe quels objets de données (par exemple reçu par l'intermédiaire de JSON parsing) à une interface (mais vos pré-vérifications devraient affirmer que ce sont vraiment des données valides). Les interfaces sont donc très flexibles pour les données.
d'un autre côté les classes ont un type associé à l'exécution et il y a du code générer. Vous pouvez vérifier le type à l'exécution avec instanceof
et il y a un prototype de chaîne installé. Si vous définissez User
en tant que classe, il ne sera pas un utilisateur valide sauf si vous appelez la fonction constructeur. Et vous ne pouvez pas définir n'importe quel type de données appropriées pour être un User
. Vous devez créer une nouvelle instance et copier les propriétés.
Ma règle personnelle de pouce:
- Si je fais face à pure data (de différentes sources), j'ai utiliser des interfaces
- si Je modélise quelque chose qui a une identité et un état (et probablement des méthodes attachées pour modifier l'état) j'utilise une classe.
comment utiliser correctement les interfaces dans TypeScript: pour établir des contrats de comportement, ou pour définir les propriétés et les objets devraient avoir?
les Interfaces en caractères typographiques sont des contrats de forme, décrivant la structure attendue d'un objet. Si une valeur a une certaine annotation d'interface, vous vous attendez à ce qu'il s'agisse d'un objet comportant les membres définis dans l'interface. Les membres peuvent être des valeurs ou des fonctions (méthodes). Généralement, leur comportement (organes de fonction) est pas partie du contrat. Mais vous pouvez spécifier s'ils sont readonly
ou pas.
alors, quelles interfaces sont prévues en écriture typographique? Pourquoi les gens utilisent-ils des interfaces en TypeScript comme nous utilisons des clases en C#?
les interfaces Typescript peuvent jouer le même rôle que les interfaces C# si on s'attend à ce qu'elles soient implémentées par des classes TypeScript.
Mais pas seulement une classe peut implémenter une interface; n'importe quel type de valeur peut:
interface HelloPrinter {
printHello(): void
}
le suivant l'objet n'est pas une classe, mais néanmoins implémente l'interface:
{
printHello: () => console.log("hello")
}
Ainsi, nous pouvons faire
const o: HelloPrinter = {
printHello: () => console.log("hello")
}
et le compilateur ne se plaindra pas.
L'objet implémente l'interface sans nous forcer à écrire une classe.
travailler avec des interfaces est plus léger que travailler avec des classes (interfaces et).
mais si vous avez besoin de connaître le nom du type (Classe/nom de l'interface) pendant l'exécution, alors les classes sont le bon choix, car les noms d'interface ne sont connus qu'au moment de la compilation.
en utilisant seulement le mécanisme de desérialisation natif, vous ne pouvez pas desérialiser une instance d'une classe spécifique. Vous ne pouvez vous désérialiser qu'en un simple objet javascript. Ces objets peuvent adhérer à des interfaces dactylographiées mais ne peuvent pas être une instance d'une classe. Si vous avez besoin de traiter des données qui traversent une limite de sérialisation telle que des données attendues d'un service Web, utilisez des interfaces. Si vous avez besoin de générer de nouvelles instances de telles valeurs vous-même, il suffit de les construire littéralement ou de créer un commodité fonction qui renvoie à des objets qui adhèrent à cette interface.
une classe peut elle-même implémenter une interface, mais elle peut devenir confuse si vous vous attendez à traiter à la fois des instances de classe construites localement et des objets simples désérialisés et reconstitués. Vous ne pourrez jamais compter sur la base de la classe de l'objet et il n'y aurait donc aucun avantage à le définir aussi comme une classe pour ce but précis.
j'ai réussi à créer un module ServerProxy responsable de l'envoi de code d'un service web - l'appel du service web et le résultat retourné. Si vous êtes lié à des modèles knock-out ou similaires, vous pouvez avoir une classe qui encapsule le modèle lié à l'interface utilisateur avec un constructeur qui sait comment soulever un objet JavaScript-simple retourné qui adhère à l'interface du webservice-seulement contrat dans une instance de votre classe de modèle.