Sub-classing an object at run time: Obj-C

Discussion in 'Mac Programming' started by MacDonaldsd, Feb 20, 2008.

  1. macrumors 65816

    MacDonaldsd

    Joined:
    Sep 8, 2005
    Location:
    London , UK
    #1
    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 ?
     
  2. macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #2
    Possible, but very tricky. I wouldn't recommend it if there's any alternative.
     
  3. macrumors 6502a

    yeroen

    Joined:
    Mar 8, 2007
    Location:
    Cambridge, MA
    #3
    Is this C++ you're talking about, or Java or Obj-C?
     
  4. thread starter macrumors 65816

    MacDonaldsd

    Joined:
    Sep 8, 2005
    Location:
    London , UK
  5. macrumors member

    Joined:
    Oct 24, 2006
    Location:
    Baltimore, MD
    #5
    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.
     
  6. macrumors 6502a

    yeroen

    Joined:
    Mar 8, 2007
    Location:
    Cambridge, MA
    #6
    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?
     
  7. thread starter macrumors 65816

    MacDonaldsd

    Joined:
    Sep 8, 2005
    Location:
    London , UK
    #7
    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.
     
  8. macrumors 68020

    Krevnik

    Joined:
    Sep 8, 2003
    #8
    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.
     
  9. macrumors newbie

    Joined:
    Dec 6, 2007
    #9
    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.
     
  10. macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #10
    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.
     
  11. thread starter macrumors 65816

    MacDonaldsd

    Joined:
    Sep 8, 2005
    Location:
    London , UK
    #11
    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
     
  12. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #12
    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
     
  13. macrumors 6502a

    Joined:
    Sep 3, 2005
    Location:
    Cramlington, UK
    #13
    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
     
  14. macrumors member

    Joined:
    Feb 21, 2008
    #14
    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?
     
  15. macrumors 6502a

    #15
    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.
     
  16. macrumors 6502

    Joined:
    May 27, 2007
    Location:
    Montreal Canada
    #16
    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 :)
     
  17. macrumors 68020

    Krevnik

    Joined:
    Sep 8, 2003
    #17
    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.
     
  18. macrumors 6502a

    #18
    Yes, fair point about the attributes, that will be more complicated.
     
  19. thread starter macrumors 65816

    MacDonaldsd

    Joined:
    Sep 8, 2005
    Location:
    London , UK
    #19
    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
     
  20. macrumors 65816

    devman

    Joined:
    Apr 19, 2004
    Location:
    AU
    #20
    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.
     
  21. macrumors G4

    Eraserhead

    Joined:
    Nov 3, 2005
    Location:
    UK
    #21
    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.
     

Share This Page