2009-03-25 4 views
0

Supposons que vous ayez un objet Person et qu'il comporte une méthode, promote(), qui le transforme en objet Captain. Comment appelez-vous ce type de méthode/interaction?Comment appelez-vous une méthode d'un objet qui change de classe?

Il se sent aussi comme une inversion de:

myCaptain = new Captain(myPerson); 

Edit: Merci à toutes les réponses. La raison pour laquelle je rencontre ce modèle (en Perl, mais pertinent n'importe où) est purement pour la commodité. Sans connaître les offres de mise en œuvre, vous pourriez dire que la classe Captain "a un" Person (je me rends compte que ce n'est peut-être pas le meilleur exemple, mais soyez assurés qu'il ne s'agit pas d'une sous-classe).

mise en œuvre, je suppose:

// this definition only matches example A 
Person.promote() { 
    return new Captain(this) 
} 

personable = new Person; 

// A. this is what i'm actually coding 
myCaptain = personable.promote(); 

// B. this is what my original post was implying 
personable.promote(); // is magically now a captain? 

donc, littéralement, il est juste une méthode pratique pour la construction d'un Captain. Je me demandais simplement si ce modèle a été vu dans la nature et s'il avait un nom. Et je suppose que oui, ça ne change pas vraiment la classe autant que ça en retourne une autre. Mais théoriquement, je ne me soucie pas vraiment de l'original. Ken ++, J'aime comment vous signalez un cas d'utilisation. Parfois, il serait vraiment génial de changer quelque chose en place, disons, un environnement sensible à la mémoire.

+0

Besoin de changer la classe à OCaptain afin que vous obteniez OCaptain myCaptain – belgariontheking

+0

Damn vous Walt Whitman – TheTXI

+0

@Rich B, je ne comprends pas vous éditant le capitaine à oCaptain. Soin d'expliquer? – strager

Répondre

5

Une méthode d'un objet ne doit pas modifier sa classe. Vous devez soit avoir un membre qui retourne une nouvelle instance:

myCaptain = myPerson->ToCaptain(); 

Ou utiliser un constructeur, comme dans votre exemple:

myCaptain = new Captain(myPerson); 

Je l'appellerais une conversion, ou même un casting, selon comment vous utilisez l'objet. Si vous avez un objet de valeur:

Person person; 

Vous pouvez utiliser la méthode constructeur pour lancer implicitement:

Captain captain = person; 

(Cela suppose C++.)

+0

myCaptain = Person.ToCaptain() peut-être? :) – TheTXI

+0

@TheTXI, Quoi? O_o – strager

+0

+1: Je pense qu'il est beaucoup plus propre de simplement permettre au constructeur "Captain" d'accepter les objets "Person" et de les refondre. Imaginez ce qui se passerait si vous aviez beaucoup d'autres classes ("Admiral", etc.) ... chaque classe aurait besoin de méthodes "To *" pour toutes les autres classes. – gnovice

5

Une solution plus simple pourrait être fait rang un propriété de la personne. Je ne connais pas votre structure de données ou vos besoins, mais si vous avez besoin de quelque chose qui tente de casser les bases d'une langue, il est probable qu'il existe une meilleure façon de le faire.

+0

Enum est une bonne idée, oui. – strager

3

Vous pourriez envisager le "State Pattern", aussi appelé parfois le motif "Objects for States". Il est défini dans le livre Design Patterns, mais vous pouvez facilement en trouver beaucoup sur Google.

Une caractéristique du motif est que "l'objet semblera changer de classe."

Voici quelques liens:

Objects for States

Pattern: State

1

Tout le monde semble être l'hypothèse d'un système d'objet C++/Java comme, peut-être à cause de la syntaxe utilisée dans la question, mais il est tout à fait possible de changer la classe d'une instance à l'exécution dans d'autres langues

Le CLOS de Lisp permet de changer la classe d'une instance à tout moment, et c'est un transformation ciente. (La terminologie et la structure sont légèrement différentes: les méthodes n'appartiennent pas aux classes de CLOS.)

Cependant, je n'ai jamais entendu un nom pour ce type spécifique de transformation. La fonction qui fait cela s'appelle simplement change-class.

Richard Gabriel seems to call it le "protocole de changement de classe", après AMOP de Kiczales, qui a formalisé comme "protocoles" plusieurs des internes de CLOS pour la métaprogrammation.

Les gens se demandent pourquoi vous voudriez faire ceci; Je vois deux gros avantages par rapport à la simple création d'une nouvelle instance:

  • plus rapide: changer de classe peut être aussi simple que mettre à jour un pointeur, et mettre à jour les emplacements qui diffèrent; Si les classes sont très similaires, cela peut être fait sans nouvelles allocations de mémoire.
  • plus simple: si une douzaine de lieux ont déjà une référence à l'ancien objet, la création d'une nouvelle instance ne changera pas ce qu'ils pointent; si vous avez besoin de mettre à jour chacun vous, qui pourrait ajouter beaucoup de complexité pour ce qui devrait être une opération simple (2 mots, en Lisp)

Cela ne veut pas dire que c'est toujours la bonne réponse, mais il est agréable de avoir la capacité de le faire quand vous le voulez. "Changer la classe d'une instance" et "créer une nouvelle instance similaire à celle-ci" sont des opérations très différentes et j'aime pouvoir dire exactement ce que je veux dire.

0

La première partie intéressante serait de savoir: pourquoi voulez-vous/besoin d'un objet change sa classe à l'exécution?

Il existe différentes options:

  • Vous le voulez répondre différemment à certaines méthodes pour un état donné de l'application.

  • Vous voudrez peut-être avoir de nouvelles fonctionnalités que la classe d'origine n'a pas.

  • Autres ...

langages typés statiquement tels que Java et C# ne permettent pas que cela se produise, parce que le type de l'objet doit être savoir au moment de la compilation.

D'autres langages de programmation tels que Python et Ruby peut permettre cela (je ne suis pas sûr, mais je sais qu'ils peuvent ajouter des méthodes à l'exécution)

Pour la première option, la réponse donnée par Charlie Flowers correct, l'utilisation des modèles d'état permettrait à une classe de se comporter différemment mais l'objet aura la même interface.

Pour la deuxième option, vous devez quand même modifier le type d'objet et l'affecter à une nouvelle référence avec les fonctionnalités supplémentaires. Vous devrez donc créer un autre objet distinct et vous obtiendrez deux objets différents.

Questions connexes