tags:

views:

249

answers:

5

Let's say you have a Person object and it has a method on it, promote(), that transforms it into a Captain object. What do you call this type of method/interaction?

It also feels like an inversion of:

myCaptain = new Captain(myPerson);

Edit: Thanks to all the replies. The reason I'm coming across this pattern (in Perl, but relevant anywhere) is purely for convenience. Without knowing any implementation deals, you could say the Captain class "has a" Person (I realize this may not be the best example, but be assured it isn't a subclass).

Implementation I assumed:

// 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?

So, literally, it's just a convenience method for the construction of a Captain. I was merely wondering if this pattern has been seen in the wild and if it had a name. And I guess yeah, it doesn't really change the class so much as it returns a different one. But it theoretically could, since I don't really care about the original.

Ken++, I like how you point out a use case. Sometimes it really would be awesome to change something in place, in say, a memory sensitive environment.

+5  A: 

A method of an object shouldn't change its class. You should either have a member which returns a new instance:

myCaptain = myPerson->ToCaptain();

Or use a constructor, as in your example:

myCaptain = new Captain(myPerson);

I would call it a conversion, or even a cast, depending on how you use the object. If you have a value object:

Person person;

You can use the constructor method to implicitly cast:

Captain captain = person;

(This is assuming C++.)

strager
myCaptain = Person.ToCaptain() perhaps? :)
TheTXI
@TheTXI, What? O_o
strager
+1: I think it is much cleaner to simply allow the "Captain" constructor to accept "Person" objects and recast them. Imagine what would happen if you had many other classes ("Admiral", etc.)... each class would need "To*" methods for every other one.
gnovice
+5  A: 

A simpler solution might be making rank a property of person. I don't know your data structure or requirements, but if you need to something that is trying to break the basics of a language its likely that there is a better way to do it.

Brian
Enum is a good idea, yes.
strager
+3  A: 

You might want to consider the "State Pattern", also sometimes called the "Objects for States" pattern. It is defined in the book Design Patterns, but you could easily find a lot about it on Google.

A characteristic of the pattern is that "the object will appear to change its class."

Here are some links:

Objects for States

Pattern: State

Charlie Flowers
+1  A: 

Everybody seems to be assuming a C++/Java-like object system, possibly because of the syntax used in the question, but it is quite possible to change the class of an instance at runtime in other languages.

Lisp's CLOS allows changing the class of an instance at any time, and it's a well-defined and efficient transformation. (The terminology and structure is slightly different: methods don't "belong" to classes in CLOS.)

I've never heard a name for this specific type of transformation, though. The function which does this is simply called change-class.

Richard Gabriel seems to call it the "change-class protocol", after Kiczales' AMOP, which formalized as "protocols" many of the internals of CLOS for metaprogramming.

People wonder why you'd want to do this; I see two big advantages over simply creating a new instance:

  • faster: changing class can be as simple as updating a pointer, and updating any slots that differ; if the classes are very similar, this can be done with no new memory allocations
  • simpler: if a dozen places already have a reference to the old object, creating a new instance won't change what they point to; if you need to update each one yourself, that could add a lot of complexity for what should be a simple operation (2 words, in Lisp)

That's not to say it's always the right answer, but it's nice to have the ability to do this when you want it. "Change an instance's class" and "make a new instance that's similar to that one" are very different operations, and I like being able to say exactly what I mean.

Ken
A: 

The first interesting part would be to know: why do you want/need an object changes its class at runtime?

There are various options:

  • You want it to respond differently to some methods for a given state of the application.

  • You might want it to have new functionality that the original class don't have.

  • Others...

Statically typed languages such as Java and C# don't allow this to happen, because the type of the object should be know at compile time.

Other programming languages such as Python and Ruby may allow this ( I don't know for sure, but I know they can add methods at runtime )

For the first option, the answer given by Charlie Flowers is correct, using the state patterns would allow a class behave differently but the object will have the same interface.

For the second option, you would need to change the object type anyway and assign it to a new reference with the extra functionality. So you will need to create another distinct object and you'll end up with two different objects.

OscarRyz