views:

102

answers:

8

Hello,

Here is the problem statement: Calling a setter on the object should result in the object to change to an object of a different class, which language can support this? Ex. I have a class called "Man" (Parent Class), and two children namely "Toddler" and "Old Man", they are its children because they override a behaviour in Man called as walk. ( i.e Toddler sometimes walks using both his hands and legs kneeled down and the Old man uses a stick to support himself).

The Man class has a attribute called age, I have a setter on Man, say setAge(int ageValue). I have 3 objects, 2 toddlers, 1 old-Man. (The system is up and running, I guess when we say objects it is obvious). I will make this call, toddler.setAge(80), I expect the toddler to change to an object of type Old Man. Is this possible? Please suggest.

Thanks,

A: 

Objects in Python can change their class by setting the __class__ attribute. Otherwise, use the Strategy pattern.

Ignacio Vazquez-Abrams
I would strongly advise to use the strategy pattern (http://en.wikipedia.org/wiki/Strategy_pattern) over changing the class of an object ad-hoc. Thinking of object instances as dynamic types makes me cringe.
Ben S
Strategy pattern would only allow me to substitute toddler with old man, and because they would be implemented as interfaces, i would not be able to reuse the other properties of "Man",I would want to keep some attributes of "Man" like mass etc. intact.That was the initial thought of choosing inheritance over typing(interfaces), maybe its not right !
panzerschreck
A: 

I wonder if subclassing is really the best solution here. A property (enum, probably) that has different types of people as its possible values is one alternative. Or, for that matter, a derived property or method that tells you the type of person based on the age.

pkananen
A: 

Javascript can do this. At any time you can take an existing object and add new methods to it, or change its existing methods. This can be done at the individual object level.

Douglas Crockford writes about this in Classical Inheritance in JavaScript:

Class Augmentation

JavaScript's dynamism allows us to add or replace methods of an existing class. We can call the method method at any time, and all present and future instances of the class will have that method. We can literally extend a class at any time. Inheritance works retroactively. We call this Class Augmentation to avoid confusion with Java's extends, which means something else.

Object Augmentation

In the static object-oriented languages, if you want an object which is slightly different than another object, you need to define a new class. In JavaScript, you can add methods to individual objects without the need for additional classes. This has enormous power because you can write far fewer classes and the classes you do write can be much simpler. Recall that JavaScript objects are like hashtables. You can add new values at any time. If the value is a function, then it becomes a method.

Jim Ferrans
+2  A: 

This sounds to me like the model is wrong. What you have is a Person whose relative temporal grouping and some specific behavior changes with age.

Perhaps you need a method named getAgeGroup() which returns an appropriate Enum, depending on what the current age is. You also need an internal state object which encapsulates the state-specific behavior to which your Person delegates behavior which changes with age.

That said, changing the type of an instantiated object dynamically will likely only be doable only with dynamically typed languages; certainly it's not doable in Java, and probably not doable in C# and most other statically typed languages.

Software Monkey
It can perfectly well be done in strongly typed languages. Python supports changing the class of an object, for example.
Jörg W Mittag
Your guess is correct--C# does not allow an object to change classes.
Jeffrey L Whitledge
Jörg: "Strongly/weakly typed" are so ill-defined as to be virtually meaningless, so he is either right or wrong, depending on your definition. It could well be that he's defining "weakly typed" to mean "instances can have their types changed" (#5 on Wikipedia's list of possible meanings).
Ken
@Jorg: Modified my answer to refer to dynamically and statically typed languages.
Software Monkey
@Ken: I know that strongly/weakly typed are essentially undefined. However, @Software Monkey cited Java and C# as examples of strongly typed languages, and I am going to state my opinion that any definition that doesn't have Python end up on the same side of the line as Java and C# isn't a very useful one. So, either all three are strong or all three are weak, depending on the definition, but having Python end up as weak and Java as strong would certainly be a very strange definition. I personally prefer Luca Cardelli's definition (who, after all, literally wrote the book on Typeful ...
Jörg W Mittag
... Programming) and he has all three ending up as strongly typed.
Jörg W Mittag
@Jorg: At the risk of beating a dead horse, I simply don't know enough about python to say one way or the other - so I restricted my comments to the two object oriented languages I *do* know something about.
Software Monkey
Jörg: I think that any definition that categorizes Python and Java/C# as having the same type system is the meaningless one. What would be the other category -- just C and assembly?
Ken
A: 

Common Lisp can: use the generic function CHANGE-CLASS.

Ken
+1  A: 

This is a common problem that you can solve using combination of OO modelling and design patterns.

You will model the class the way you have where Toddler and OldMan inherit from Man base class. You will need to introduce a Proxy (see GoF design pattern) class as your access to your Man class. Internally, proxy hold a man object/pointer/reference to either Toddler or OldMan. The proxy will expose all the interfaces that is exposed by Man class so that you can use it as it is and in your scenario, you will implement setAge similar to the pseudo code below:

public void setAge(int age)
{
   if( age > TODDLER_MAX && myMan is Toddler)
     myMan = new OldMan();
   else 
    .....
   myMan.setAge(age);   
}
Fadrian Sudaman
+1  A: 

If your language does not support changing the classtype at runtime, take a look at the decorator and strategy patterns.

Ozan
A: 

I am surprised no one so far seemed to notice that this is the exact case for the State design pattern (although @Fadrian in fact described the core idea of the pattern quite precisely - without mentioning its name).

The state pattern is a behavioral software design pattern, also known as the objects for states pattern. This pattern is used in computer programming to represent the state of an object. This is a clean way for an object to partially change its type at runtime.

The referenced page gives examples in Java and Python. Obviously it can be implemented in other strongly typed languages as well. (OTOH weakly typed languages have no need for State, as these support such behaviour out of the box.)

Péter Török