Changing an instance's class

Discussion in 'Mac Programming' started by Richard Birkett, Nov 21, 2011.

  1. Richard Birkett macrumors member

    Joined:
    Aug 21, 2011
    #1
    Is it possible an any way to change the class of an instance to its parent or sister?

    It's quite a simple question in all its complexity but I will still give you context: The parent is 'Expression' with children 'Term', AdditiveExpression', 'ExponentialExpression', 'MultiplicitiveExpression', with 'AdditiveExpression' having a very similar child called 'ComplexTerm'. As you might have guessed, it is a mathematical mini-framework. The idea is that they all override the 'Expression' basic methods (or adhere to the 'Expression' protocol, I'm slightly undecided or which approah to take at this moment) so that I can ask for any expression like this:
    Code:
    - (Expression *) doSomething:(Expression *)anyExpression
    So that I know I can tell anyExpression to multiply:anotherExpression. The actual overrides will be different in themselves but all take and return the 'Expression' type. The thing is I'd like to be able to modify expressions, that is if I had a 'Term' called 'a' and an 'AdditiveExpression' called 'b' and said
    Code:
    [a multiply:b];
    naturally a must result in an additive expression ie x(y+z)=xy+xz, so I would like to be able to modify the class of 'a' from 'Term' to 'AdditiveExpression', thus allowing me to treat these as mathematical objects that manage themselves rather that something I have to be able to predict.

    Anyway, I probably made that question much more complex than the first line of this post.

    Thanks in advance,

    Richard
     
  2. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #2
    Google around for isa swizzling. Every object as an isa ivar inherited from NSObject that points to the object's class.

    However, this will only work if your subclasses don't add any instance variables.

    But it's better if you don't do this. It's hacky. And actually I don't know if it works in the new runtime (iOS and 64-bit Mac).


    I don't understand your example though. I would have thought [a multiply:b] would return a new Expression object, being actually an AdditiveExpression object. I don't understand why you'd want to mutilate a.
     
  3. Richard Birkett thread starter macrumors member

    Joined:
    Aug 21, 2011
    #3
    Thanks for the reply,

    Thanks for the tip but I'm not up for risky hacky stuff like that.

    In an equation it would be helpful to use what I call 'augmenting methods' because they are similar in function to augmented assignment operators e.g. a*=b; or [a multiply:b]; this would be helpful where I want to send a whole equation the same message so pseudo:
    Code:
    equation a = '4y=2x+1'
    [a divide:4]
    where the equation divide sends the divide:4 to all of it's terms
    this therefore results in 'a' having a value of 'y=x/2+1/4'

    Yes I could say
    Code:
    Expression *a = [a multiply:b];
    but I am already setting up a way of doing both, also the problem with the above is that if I had said c=a then 'c' will lose its association to the 'a' I am using because 'a' would point somewhere else, correct me if I'm wrong.
     
  4. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #4
    It may be altogether better if you don't even make your objects mutable, but return new objects as the result of any calculation. Look at the "stringBy..." methods as an example.
     
  5. Richard Birkett thread starter macrumors member

    Joined:
    Aug 21, 2011
    #5
    Thanks for your suggestion, I'll come back to this point if I need to, you guys have given me all the help I need so far.
    One small thing...
    What is point point of methods like stringWithString in classes that implement NSCopying? Especially since [theObject copy]; is much easier than [theClass objectWithObject:theObject];
     
  6. jared_kipe, Nov 21, 2011
    Last edited: Nov 21, 2011

    jared_kipe macrumors 68030

    jared_kipe

    Joined:
    Dec 8, 2003
    Location:
    Seattle
    #6
    This was exactly what I was thinking. You shouldn't CHANGE the class or type of an expression by operating on it. You should just return the new Expression.

    ----------

    NSString is a class cluster, the underlying details are complicated.

    Maybe 'theClass' is a mutable subclass of whatever 'theObject' is, or the other way around.

    EDIT: Oh and you might want to look at implementing Expression as a tree of expressions. (from your example I assume its a string which I hope is not true)
     
  7. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #7
    I think your design is overly complex. You'd be much better off with a tree of objects, instead of a tree of classes. For example, a binary expression tree.
    http://en.wikipedia.org/wiki/Binary_expression_tree

    One result is that expressions become Additive or Multiplicative (or anything else) simply because of where they're placed in the tree. Or more specifically, due to the nature of the operator associated with a tree node.

    Also, transformations can be achieved simply by rearranging nodes. The class never needs to change.


    You haven't described the context for why you're writing a math framework, so there may be some reason why an expression tree would be unacceptable. If it's just a general math framework, though, then I think expression trees are a better bet.
     
  8. Richard Birkett thread starter macrumors member

    Joined:
    Aug 21, 2011
    #8
    Expression trees

    Hello both,

    Thanks for the input about expression trees, I don't see how my design is so different though, I see classes like 'AdditiveExpression' as a class similar to the '+' node etc, it would have an array which contains the expressions within.
    e.g. (4^a)(3b+c) would consist of a 'MultiplicitiveExpression' instance containing an 'ExponentialExpression' instance and 'AdditiveExpression' instance, the contents of these would be made up of further expressions which in this case would be simply 'Term's but could be anything, if I wanted to multiply this out I'd send the 'MultiplicitiveExpression' instance a message to do so, it would return an 'AdditiveExpression' instance with two 'MultiplicitiveExpression' instances etc... resulting in: (3b(4^a))+(c(4^a)) essentially rearrangement.
    It wouldn't be an NSTree but it is still basically a tree. I really struggle to see where you're coming from to be honest. Could you tell me how exactly with a comparison that way would be better, and how it would work.
     
  9. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #9
    The difference is in generality.

    You have a separate subclass for every operation that can be performed on two operands. Each subclass represents both a node in a tree AND an operator acting on operands.

    Furthermore, your original post presumes expressions and terms are mutable: they can modify themselves and their children, changing the operator and thus the class (expression or term). So when you tell an operand to "multiply by X", where X is any other operand, the target object must be able to change its own intrinsic operator.

    If you'd made it so "multiply by X" returns a new expression object (operand) that represents the rearranged result of multiplying by X, then you'd have avoided the need for changing the class of objects. But you didn't do that.


    In an expression tree, there's only one Node class for representing all relationships in the tree. Each Node has space for two operands and an operator. The operands are Nodes or Terms (you can make that a subclass relationship or a protocol). The operator is a simple action that operates on two operands (call it the Operator class). The Node and Term objects have a simple method that evaluates and returns the value represented by the object, by evaluating the operands using the Operator, or in the case of a Term, simply returning the value. There's no need for separate subclasses, like MultiplicativeNode or AdditiveNode, because the operator is an assignable value (conceptually an assignable property) of the Node, rather than being intrinsic to the class of the node. The mathematical operation is the sole responsibility of the assigned Operator. The structure of operands is the responsibility of the Node.

    In your design, changing an operator requires changing the class of the node in the tree, which is what your original question was premised on. That's because the operator (say, addition or multiplication) is intrinsically defined by the same class that maintains the tree structure. That is, you can't separate structure (operand relationships) from operators.

    In an expression tree, changing an operator simply assigns a different operator object to a Node. It's the difference between is-a (your design) and has-a (the expression tree). In an expression tree, a Node has-a leftOperand, has-a rightOperand, and has-a Operator. In your design, a node has-a leftOperand, has-a rightOperand, but is-a Operator. Changing the operatore requires changing what the node is, i.e. changing its class.

    http://en.wikipedia.org/wiki/Has-a
    http://en.wikipedia.org/wiki/Is-a

    If you consider the expression tree design, and define the Node so the Operator is assigned only at creation and is read-only (immutable), then you effectively have your design: operator tied to node and can't be changed. This shows that an expression tree can emulate your design. But your design can't act like an expression tree, unless you do tricky hacks like changing the class of the tree nodes. Therefore, expression tree is more general and more flexible.


    I don't know why you'd rearrange this expression: (4^a)(3b+c)
    into this one: (3b(4^a))+(c(4^a))
    since you're increasing the number of operators and operands. Seems wrong to me, but maybe I'm not seeing the purpose.
     
  10. Richard Birkett thread starter macrumors member

    Joined:
    Aug 21, 2011
    #10
    Thank you very much for your reply.

    I understand what you say there, I will definitely use immutable objects since I will often need to change the subclass. I don't see this as a massive problem since there won't be anything asking for a specific subclass. The point of having subclasses is to be tidy and keep different bits of code separate, for manageability (the windows version with only 'Term's is already about 1000 lines), when an operation occurs, the class property will be used to determine which method to use.
    I am officially ditching class changing and mutability from now :).
    Again... Tell me if there is a simpler way to do the complex thing I want to do... which brings me to the next point...

    The purpose of this app is a very powerful algebra muncher that will solve what you give it.
    That is why I need to be able to rearrange in anyway I would like to define. I do like the binary tree idea if it is more simple for everything I need but it couldn't really be binary, I don't like the added complexity if you have more than 2 of something e.g. a+b+c+d would get a bit complicated as far as messaging the operator objects is concerned, the operator wouldn't actually know what is in it, but an additive expression with infinite length would. For example at the moment I am finishing off the vb version of the app (so that I can easily convert it) which can solve simultaneous equations, this involves a lot of querying monomials in varying lengths of polynomial equations for their properties (mainly their variables). I don't want to have to set up a load of chain messaging down a tree. The moral of my story is no BINARY, even if I use a tree.

    :)
     

Share This Page