Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

MacDonaldsd

macrumors 65816
Original poster
Sep 8, 2005
1,005
0
London , UK
Hi,

Is it possible to subclass an object at runtime. i.e. Can I create an object as the super class and decide what subclass it will become at a later date ?
 

deathdruid

macrumors member
Oct 24, 2006
38
2
Cambridge, MA, USA
Certainly possible in Java.

Code:
Object o;
if(x == 1) {
    o = new Integer();
} else {
    o = new String();
}
System.out.println(o);

There should be something similar in Objective-C; maybe someone else can tell you how.
 

yeroen

macrumors 6502a
Mar 8, 2007
944
2
Cambridge, MA
Do you need to build the derived object 'on top of' the base class object, i.e. at the same starting memory address? Or is it sufficient to copy the contents of the base class object as part of a new derived object?
 

MacDonaldsd

macrumors 65816
Original poster
Sep 8, 2005
1,005
0
London , UK
Do you need to build the derived class 'on top of' the base class object, i.e. at the same starting memory address? Or is it sufficient to copy the contents of the base class as a component of a new derived class?

Im going to be using it within core data so it will be related to other objects.

But I was thinking the same as you, (well what i think your thinking).

Simply create a new object and copy the values across and remove the old object.
 

Krevnik

macrumors 601
Sep 8, 2003
4,101
1,312
Okay, I am going to put forward what I think you said in the original post, and answer that. :)

I think what you are trying to do is create a 'Car' object, and then when you find out the 'Car' is really a 'Ford', change the type of the object so it is now a 'Ford'.

The catch is that even with dynamically typed languages like Obj-C, you can't change the type of an object once it has been created. What you /can/ do though is this: When you have the superclass object and want to turn it into the subclass, then /create/ a new copy of the subclass, and write an init method that can take the superclass and copy data from it. It is a copied object, but now it is a copied object of the type you want.
 

skinnybeans

macrumors newbie
Dec 6, 2007
17
0
Im not very familiar with objective c syntax, so I'll explain in c++ terms what you want to do.

You need to declare a pointer to the base class object. Using the car example above..

Car *theCar;

Then later when you know what kind of object you want to create:

theCar = new Ford();

Then you can pass the value of theCar where ever a car object can be used.

This is a classic example of inheritance and polymorphism. So if you want to understand this topic in more depth read up on those 2 areas.
 

Catfish_Man

macrumors 68030
Sep 13, 2001
2,579
2
Portland, OR
Heh. I interpreted the request as being a much much more difficult one, transforming *a specific instance* of a class into an instance of another class.

Bar foo = new Bar();
Baz transformedFoo = foo.transformInto(Baz);

Which is possible in ObjC, but very tricky, and not without tradeoffs.
 

MacDonaldsd

macrumors 65816
Original poster
Sep 8, 2005
1,005
0
London , UK
Hi guys thanks for all your thoughts.

Il give an example of what I mean.

If I have a Person class with the attributes name and email


I then have two subclass Teacher and Student

Student has attributes year of study, course etc

Teacher has attributes degree, teaches etc.

Is it possible to create a Person with there attributes and decide latter whether there a student or a teacher.

P.S. I realise you wouldn't want to do that in real life its just a clear example
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
Not easily. The simplest way would be to define a constructor for both Teacher and Student that accept a Person as an argument. Something like initWithPerson: and use that to create a Student or Teacher from the Person
 

lazydog

macrumors 6502a
Sep 3, 2005
709
6
Cramlington, UK
I'm not entirely sure this would work but I guess the way to transform a Person into a Student would be to overwrite in memory the old Person object with the new Student object at the exact same memory address. It would be tricky to do because you'd have to make sure the Student object would fit within the memory space of the original Person object. I think you could do it in C++ because you can overload the new() and delete() operators.

A way round this is to use, throughout your code, pointers to pointers for all your Person objects. You could then reallocate the underlying Person object as a Student or Teacher without affecting the references to it in your code.

A fancier way would be to use a proxy class, eg PersonProxy, that containsd as a member a Person, Student or Teacher instance member which you can change at any time. But I guess that's straying too far from your question.

Having said all that… I'm not entirely sure why you would want to do it!

I hope all that makes sense!

b e n
 

alaceo

macrumors member
Feb 21, 2008
32
0
I know this would work well on C++ through polymorphism and dynamic casting, but I'm not sure if dynamic casting is available/what it is like on ObjC. Maybe there's some dynamic casting info available on the Apple Dev site?
 
Sounds to me like you want to use a delegate. You have a class Person that you want to adapt at runtime.

Some pseudo code (sorry, am not an Obj-C person):

Code:
// The SchoolAttendee interface has a function called goToClass
Interface SchoolAttendee:
    function goToClass()

// A Teacher class provides an implementation where in class they teach()
Class Teacher implements SchoolAttendee:
    function gotToClass() { teach() }

// By contrast, a student learn()[i]s[/i] when they go to class  
Class Student implement SchoolAttendee:
    function goToClass() { learn() }

// your actual person (note: while not specified, this can implement goToClass())
Class Person:
    SchoolAttendee schoolAction = null;

    // the function enrollInClass sets the behaviour when the person is in class
    // this behaviour could be set at creation time (I think in the wikipedia article)
    function enrollInClass(SchoolAttendee action) { schoolAction = action }

    function goToClass() { if schoolAction is not null: schoolAction.goToClass() }

// An example
main:
    // At the start create a Person
    Person person

    // ... later in the program, the person enrols in a class
    // ... in this case pass a Teacher object
    person.enrollInClass(Teacher())

    // when the person goesToClass, it will call the function teach()
    person.goToClass()

Note, this example sets the behaviour at runtime, you can see some other examples, including Obj-C, at the wikipedia article ( http://en.wikipedia.org/wiki/Delegation_pattern ) but there are lots of ways to implement this.

A language like Python can handle this very elegantly, where you can add methods to a class at runtime.

I *think* that, from what little I have read about Obj-C, you would only need to provide a class that implements a function with the appropriate name (aka an informal protocol). I am sure someone here, or your Obj-C reference book, can give you the details.
 

Animalk

macrumors 6502
May 27, 2007
471
19
Montreal Canada
There are several possible patterns that can be used to create such functionality. I highly recommend you read up on the Factory pattern which is the general case of what you're essentially trying to do.

Happy coding :)
 

Krevnik

macrumors 601
Sep 8, 2003
4,101
1,312
Sounds to me like you want to use a delegate. You have a class Person that you want to adapt at runtime.

Note, this example sets the behaviour at runtime, you can see some other examples, including Obj-C, at the wikipedia article ( http://en.wikipedia.org/wiki/Delegation_pattern ) but there are lots of ways to implement this.

I *think* that, from what little I have read about Obj-C, you would only need to provide a class that implements a function with the appropriate name (aka an informal protocol). I am sure someone here, or your Obj-C reference book, can give you the details.

Yes, I like this idea and hadn't considered it first off. :)

The catch is that this works /best/ when you want to override method behavior though. If you want to add data to the class as well, then things get trickier.

You can still get away with this using KVC for your data though, by letting the delegate also provide a KVC answer if the base class has none.
 

MacDonaldsd

macrumors 65816
Original poster
Sep 8, 2005
1,005
0
London , UK
Thanks for everyone's input, it has turned into quite an intriguing discussion.

Im going to take the easier root and simple copy the the information from one object to another, and do this in a constructor in the subclass as robbieduncan suggested.

This is mainly down to the fact as once it has sub-classed it will stay as that class, and I will also be saving the object to manipulate it at a later date, so in the grand scheme of things it will make it much easier to do it like this.

Thanks for all the help and all the links :D
 

devman

macrumors 65816
Apr 19, 2004
1,242
8
AU
Hi guys thanks for all your thoughts.

Il give an example of what I mean.

If I have a Person class with the attributes name and email


I then have two subclass Teacher and Student

Student has attributes year of study, course etc

Teacher has attributes degree, teaches etc.

Is it possible to create a Person with there attributes and decide latter whether there a student or a teacher.

P.S. I realise you wouldn't want to do that in real life its just a clear example

Inheritance is the wrong choice here. Teachers and Students aren't special kinds of people; they are roles that people play. What if a person is both a student and a teacher? (that's just one of several problems with inheritance here). Composition is the way to go. Look at the role pattern (Coad '95) which will also solve your problem of deciding later if a person is playing the role of teacher or student or both. Furthermore, your example focuses only on data (attributes). It is behavior (methods) that drive a good object model.
 

Eraserhead

macrumors G4
Nov 3, 2005
10,434
12,250
UK
Not easily. The simplest way would be to define a constructor for both Teacher and Student that accept a Person as an argument. Something like initWithPerson: and use that to create a Student or Teacher from the Person

Sounds like the way forward to me, I'd set it up to have a Person, Teacher and Student object in the model, then if you want a teacher you create a teacher object and link it to the person with a relationship, the same for a student.

In theory that may allow you to work with Postgraduates and other strange people who might be both teachers and students :p.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.