2009-02-12 6 views
1

Étant donné un ensemble de classes de tuple dans un langage OOP: Pair, Triple et Quad, devrait Triple paire sous-classe, et sous-classe Quad Triple? Le problème, tel que je le vois, est de savoir si un Triple devrait être substituable en tant que Pair, et de même Quad pour Triple ou Pair. Si Triple est également une paire et Quad est également un Triple et une paire. Dans un contexte, une telle relation pourrait être utile pour l'extensibilité - aujourd'hui, cette chose renvoie une paire de choses, demain j'en ai besoin pour retourner un triple sans casser les appelants existants, qui n'utilisent que les deux premiers des trois.Les tuples doivent-ils se sous-classer les uns les autres?

D'un autre côté, devraient-ils être chacun de types distincts? Je peux voir des avantages dans la vérification de type plus forte - où vous ne pouvez pas passer un Triple à une méthode qui attend une paire.

Je penche pour l'utilisation de l'héritage, mais j'apprécierais vraiment l'apport des autres? PS: Au cas où cela serait important, les classes seront (bien sûr) génériques. PPS: D'un point de vue plus subjectif, les noms devraient-ils être Tuple2, Tuple3 et Tuple4?


Edit: Je pense à ces groupes plus que faiblement couplés; pas spécifiquement pour des choses comme les coordonnées x/y x/y/z, bien qu'ils puissent être utilisés pour cela. Ce serait des choses comme avoir besoin d'une solution générale pour plusieurs valeurs de retour d'une méthode, mais sous une forme avec une sémantique très simple. Cela dit, je suis intéressé par toutes les façons dont les autres ont utilisé des tuples.

Répondre

1

La longueur différente d'un tuple est un type différent. (Eh bien, dans de nombreux systèmes de type de toute façon.) Dans une langue fortement typée, je ne pense pas qu'ils devraient être une collection.

Ceci est une bonne chose car elle assure plus de sécurité. Les endroits où vous renvoyez des tuples ont généralement des informations quelque peu couplées avec elles, la connaissance implicite de ce qu'est chaque composant. C'est pire si vous passez plus de valeurs dans un tuple que prévu - qu'est-ce que cela veut dire? Cela ne correspond pas à l'héritage.

Un autre problème potentiel est si vous décidez d'utiliser une surcharge. Si les tuples héritent l'un de l'autre, la résolution de surcharge échouera là où elle ne le devrait pas. Mais c'est probablement un meilleur argument contre la surcharge.

Bien sûr, rien de tout cela n'a d'importance si vous avez un cas d'utilisation spécifique et constatez que certains comportements vous aideront. Editer: Si vous voulez des informations générales, essayez un peu de famille Haskell ou ML (OCaml/F #) pour voir comment ils sont utilisés et ensuite prendre vos propres décisions.

+0

Pouvez-vous améliorer votre réponse avec un exemple (rapide/simple) de l'échec de la surcharge? –

+0

BTW, c'était en jouant avec Haskell que j'ai d'abord été exposé au concept des tuples. :) –

0

J'irais avec 0,1,2 ou infini. par exemple. null, 1 objet, votre classe Pair, ou alors une collection de quelque sorte. Votre paire pourrait même implémenter une interface de collection.

S'il existe une relation spécifique entre trois ou quatre éléments, elle devrait probablement être nommée.

[Peut-être que je manque le problème, mais je ne peux pas penser à un cas où je veux créer un lien particulier 3 choses de façon générique]

+0

J'aime l'idée d'être une collection; probablement Liste. Non map, car Pair n'est pas censé être l'équivalent de Map.Entry. –

1

Il me semble que vous devriez faire un générique Tuple interface (ou utiliser quelque chose comme la collection mentionnée ci-dessus), et ont votre paire et classes 3-tuple implémenter cette interface. De cette façon, vous pouvez tirer parti du polymorphisme, mais aussi permettre à une paire d'utiliser une implémentation plus simple qu'un tuple de taille arbitraire. Vous voudrez probablement faire en sorte que votre interface Tuple inclue les raccourcis .x et .y comme raccourcis pour les deux premiers éléments, et les tuples plus grands peuvent implémenter leurs propres raccourcis en fonction des éléments avec des indices plus élevés.

1

cela dépend de la sémantique que vous avez besoin -

  • une paire d'opposés n'est pas sémantiquement compatible avec un 3-tuple d'objets similaires
  • une paire de coordonnées dans l'espace polaire n'est pas sémantiquement compatible avec un 3-tuple de coordonnées dans l'espace euclidien

si votre sémantique sont des compositions simples, puis un tuple de classe générique <N> serait plus logique

1

Comme la plupart des questions liées à la conception, la réponse est - Cela dépend.

Si vous êtes à la recherche d'un design Tuple conventionnel, Tuple2, Tuple3 etc est le chemin à parcourir. Le problème avec l'héritage est que, tout d'abord, Triplet n'est pas un type de paire. Comment implémenteriez-vous la méthode d'égalité pour cela? Un triplet est-il égal à une paire avec les deux premiers éléments identiques? Si vous avez une collection de paires, pouvez-vous lui ajouter un triplet ou vice versa? Si dans votre domaine c'est bien, vous pouvez aller avec l'héritage.

Dans tous les cas, il est payant d'avoir une interface/classe abstraite (peut-être Tuple) que tout cela implémente.

+0

@ amit.dev: Quelles méthodes l'interface Tuple doit-elle déclarer? –

+0

@ amit.dev: Je pense qu'un Triple n'est pas "égal à()" une paire, parce que Pair.getClass()! = Triple.getClass() - permettant somePair.equals (someTriple) violerait le contrat d'égalité parce que someTriple .equals (somePair) doit sûrement être faux. –

+0

@ amit.dev: Mais parce que somePair n'est pas égal à someTriple, cela ne signifie pas que someTriple n'est pas une instanceof Pair. –

0

Gilad Bracha blogged about tuples, que j'ai trouvé intéressant de lire.

Un point il a fait (que ce soit correctement ou non, je ne peux pas encore juger) était:

tuples littérales sont mieux définis en lecture seule. Une raison à cela est que les tuples en lecture seule sont plus polymorphes. Les tuples longs sont des sous-types de tuples courts:

{S. T.U. V} < = {S. T. U} < = {S. T} < = {S}

[et] lecture seule tuples sont covariant:

T1 = T2 <, S1 = S2 < ==> {S1. T1} < = {S2.T2}

Cela semble suggérer mon inclination à l'utilisation de l'héritage peut être correct, et serait en contradiction avec amit.dev quand il dit qu'un Triple est pas une paire.

+0

Oui l'immutabilité est agréable. Mais je ne vois aucune raison pour le sous-typage, donc Triple hérite de la paire. – MichaelGG

Questions connexes