Je sais que cela semble être une question étrange, car l'intérêt de deux ou plusieurs objets partageant la même classe est que leur comportement est le même, c'est-à-dire que leurs méthodes sont identiques.
Cependant, je suis curieux de savoir s'il existe des langages POO qui vous permettent de redéfinir les méthodes des objets de la même manière que vous pouvez attribuer différentes valeurs à leurs champs. Le résultat serait des objets construits à partir de la même classe ne présentant plus exactement le même comportement.
Si je ne me trompe pas, vous pouvez faire ce JavaScript? Parallèlement à cette question, je demande, pourquoi quelqu'un voudrait-il faire cela?
object-oriented
programming-languages
Niko Bellic
la source
la source
setClickHandler()
méthode et de faire faire des choses très différentes à différentes instances de la même classe. Dans les langues qui n'ont pas d'expressions lambda pratiques, il est plus facile de créer une nouvelle sous-classe anonyme juste pour un nouveau gestionnaire. Traditionnellement, les méthodes prioritaires étaient considérées comme la marque d'une nouvelle classe, alors que la définition des valeurs des attributs ne l'était pas, mais en particulier avec les fonctions de gestionnaire, les deux ont des effets très similaires, de sorte que la distinction devient une guerre des mots.Réponses:
Les méthodes de la plupart des langages POO (basés sur les classes) sont fixées par type.
JavaScript est basé sur un prototype et non sur une classe et vous pouvez donc remplacer les méthodes sur une base par instance car il n'y a pas de distinction stricte entre "classe" et objet; en réalité, une "classe" en JavaScript est un objet qui est comme un modèle de fonctionnement des instances.
Tout langage qui permet des fonctions de première classe, Scala, Java 8, C # (via les délégués), etc., peut agir comme si vous aviez des substitutions de méthode par instance; vous devez définir un champ avec un type de fonction, puis le remplacer dans chaque instance.
Scala a une autre possibilité; Dans Scala, vous pouvez créer des singletons d'objet (en utilisant le mot-clé object au lieu du mot-clé class), afin de pouvoir étendre votre classe et remplacer les méthodes, résultant en une nouvelle instance de cette classe de base avec des remplacements.
Pourquoi quelqu'un ferait cela? Il pourrait y avoir des dizaines de raisons. Il se pourrait que le comportement me soit plus étroitement défini que ne le permettrait l'utilisation de diverses combinaisons de champs. Il pourrait également maintenir le code découplé et mieux organisé. En général cependant, je pense que ces cas sont plus rares et il existe souvent une solution plus simple en utilisant des valeurs de champ.
la source
Il est difficile de deviner la motivation de votre question, et donc certaines réponses possibles pourraient ou non répondre à votre intérêt réel.
Même dans certains langages non prototypes, il est possible d'approximer cet effet.
En Java, par exemple, une classe interne anonyme est assez proche de ce que vous décrivez - vous pouvez créer et instancier une sous-classe de l'original, en remplaçant uniquement la ou les méthodes que vous souhaitez. La classe résultante sera
instanceof
la classe d'origine, mais ne sera pas la même classe.Quant à savoir pourquoi vous voudriez faire cela? Avec les expressions lambda Java 8, je pense que la plupart des meilleurs cas d'utilisation disparaissent. Avec les versions antérieures de Java, au moins, cela peut éviter une prolifération de classes triviales à usage étroit. C'est-à-dire que lorsque vous avez un grand nombre de cas d'utilisation liés, qui ne diffèrent que de manière minuscule, vous pouvez les créer presque à la volée (presque), avec la différence de comportement injectée au moment où vous en avez besoin.
Cela dit, même avant J8, cela peut souvent être refactorisé pour déplacer la différence dans un champ ou trois, et les injecter dans le constructeur. Avec J8, bien sûr, la méthode elle-même peut être injectée dans la classe, bien qu'il puisse y avoir une tentation de le faire lorsqu'un autre refactoring peut être plus propre (si ce n'est pas aussi cool).
la source
Vous avez demandé n'importe quelle langue fournissant des méthodes par instance. Il existe déjà une réponse pour Javascript, alors voyons comment cela se fait en Common Lisp, où vous pouvez utiliser les spécialistes EQL:
Pourquoi?
Les spécialistes EQL sont utiles lorsque l'argument soumis à la répartition est censé avoir un type qui a du
eql
sens: un nombre, un symbole, etc. En règle générale, vous n'en avez pas besoin et vous devez simplement définir autant de sous-classes que nécessaire par votre problème. Mais parfois, il suffit de répartir en fonction d'un paramètre qui est, par exemple, un symbole: unecase
expression serait limitée aux cas connus dans la fonction de répartition, tandis que les méthodes peuvent être ajoutées et supprimées à tout moment.En outre, la spécialisation sur les instances est utile à des fins de débogage, lorsque vous souhaitez inspecter temporairement ce qui se passe avec un objet spécifique dans votre application en cours d'exécution.
la source
Vous pouvez également le faire dans Ruby en utilisant des objets singleton:
Produit:
Quant aux utilisations, c'est en fait ainsi que Ruby fait les méthodes de classe et de module. Par exemple:
Définit en fait une méthode singleton
hello
sur l'Class
objetSomeClass
.la source
extend
réalité, il suffit de créer la classe singleton pour l'objet, puis d'importer le module dans la classe singleton.Vous pouvez considérer les méthodes par instance comme vous permettant d'assembler votre propre classe au moment de l'exécution. Cela peut éliminer beaucoup de code de colle, ce code qui n'a d'autre but que de mettre deux classes ensemble pour se parler. Les mixins sont une solution un peu plus structurée aux mêmes types de problèmes.
Vous souffrez un peu du paradoxe du blub , essentiellement qu'il est difficile de voir la valeur d'une fonctionnalité de langage avant d'avoir utilisé cette fonctionnalité dans un vrai programme. Recherchez donc les opportunités où vous pensez que cela pourrait fonctionner, essayez-les et voyez ce qui se passe.
Recherchez dans votre code des groupes de classes qui ne diffèrent que par une seule méthode. Recherchez des classes dont le seul but est de combiner deux autres classes dans des combinaisons différentes. Recherchez des méthodes qui ne font rien d'autre que de passer un appel à un autre objet. Recherchez des classes instanciées à l'aide de modèles de création complexes . Ce sont tous des candidats potentiels à remplacer par des méthodes par instance.
la source
D'autres réponses ont montré comment cela est une caractéristique commune des langages dynamiques orientés objet, et comment il peut être émulé trivialement dans un langage statique qui a des objets fonction de première classe (par exemple les délégués en c #, les objets qui remplacent operator () en c ++) . Dans les langages statiques qui n'ont pas une telle fonction, c'est plus difficile, mais cela peut toujours être réalisé en utilisant une combinaison du modèle de stratégie et d'une méthode qui délègue simplement sa mise en œuvre à la stratégie. C'est en fait la même chose que vous feriez en c # avec les délégués, mais la syntaxe est un peu plus compliquée.
la source
Vous pouvez faire quelque chose comme ça en C # et dans la plupart des autres langages similaires.
la source
Conceptuellement, même si dans un langage comme Java toutes les instances d'une classe doivent avoir les mêmes méthodes, il est possible de les faire apparaître comme si elles n'en avaient pas en ajoutant une couche supplémentaire d'indirection, éventuellement en combinaison avec des classes imbriquées.
Par exemple, si une classe
Foo
peut définir une classe imbriquée abstraite statiqueQuackerBase
qui contient une méthodequack(Foo)
, ainsi que plusieurs autres classes imbriquées statiques dérivant deQuackerBase
, chacune avec sa propre définition dequack(Foo)
, alors si la classe externe a un champquacker
de typeQuackerBase
, alors elle peut définissez ce champ pour identifier une instance (éventuellement singleton) de l'une de ses classes imbriquées. Après cela, l'invocationquacker.quack(this)
exécutera laquack
méthode de la classe dont l'instance a été affectée à ce champ.Comme il s'agit d'un modèle assez courant, Java inclut des mécanismes pour déclarer automatiquement les types appropriés. De tels mécanismes ne font vraiment rien qui ne pourrait pas être fait en utilisant simplement des méthodes virtuelles et des classes statiques éventuellement imbriquées, mais ils réduisent considérablement la quantité de passe-partout nécessaire pour produire une classe dont le seul but est d'exécuter une seule méthode au nom de une autre classe.
la source
Je crois que c'est la définition d'un langage "dynamique" comme ruby, groovy & Javascript (et bien d'autres). Dynamique fait référence (au moins en partie) à la capacité de redéfinir dynamiquement comment une instance de classe peut se comporter à la volée.
Ce n'est pas une grande pratique OO en général, mais pour de nombreux programmeurs de langage dynamique, les principes OO ne sont pas leur priorité absolue.
Cela simplifie certaines opérations délicates comme Monkey-Patching où vous pouvez modifier une instance de classe pour vous permettre d'interagir avec une bibliothèque fermée d'une manière qu'ils n'avaient pas prévue.
la source
Je ne dis pas que c'est une bonne chose à faire, mais cela est trivialement possible en Python. Je ne peux pas penser à un bon cas d'utilisation du haut de ma tête, mais je suis sûr qu'ils existent.
la source