Mac Changing an instance's class

Richard Birkett

macrumors member
Original poster
Aug 21, 2011
30
0
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
 

jiminaus

macrumors 65816
Dec 16, 2010
1,449
1
Sydney
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.
 

Richard Birkett

macrumors member
Original poster
Aug 21, 2011
30
0
Thanks for the reply,

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).
Thanks for the tip but I'm not up for risky hacky stuff like that.

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.
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.
 

gnasher729

macrumors P6
Nov 25, 2005
16,954
3,855
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.
 

Richard Birkett

macrumors member
Original poster
Aug 21, 2011
30
0
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];
 

jared_kipe

macrumors 68030
Dec 8, 2003
2,967
1
Seattle
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.
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.

----------

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];
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)
 
Last edited:

chown33

Moderator
Staff member
Aug 9, 2009
8,779
5,159
vertical
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.
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.
 

Richard Birkett

macrumors member
Original poster
Aug 21, 2011
30
0
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.
 

chown33

Moderator
Staff member
Aug 9, 2009
8,779
5,159
vertical
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.
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.
 

Richard Birkett

macrumors member
Original poster
Aug 21, 2011
30
0
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...

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.
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.

:)
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.