I am using objects that conform to an obj c protocol to represent a calculation. There are constants [1], variables [x], and operations [a+b]. All of these objects are immutable (the variable contains a key (to a dictionary) and a default value (to be used if the dictionary doesn’t contain a value for the key)).
Since the objects are immutable, I would like to simplify the calculation if possible when an object is initialized. (Note: The variable dictionary is allowed to continuously change, so I am never able to simplify based on the value of a variable, only constants).
For example, a very common use will be to increment a variable by 1: [[x]+1]. When these are nested, I would like to return [[x]+2] from init instead of [[[x]+1]+1] so that that part of the calculation only has to be done once. So far so good.
When both arguments are constants (e.g. [2+2]) it makes sense to just return [4]. But ARC complains about this because [4] is a different class that adheres to the same protocol.
It got me thinking about whether what I want to do is good form. I would normally make them all inherit from a single class (class cluster), but I want to use NSNumber (extended via category) for the constants.
I could move the simplification logic to another method, but that would mean having to allocate extra objects fairly often, and I would have to remember to always call it: [[[MyClass alloc]init]simplifiedCalc].
My options are:
- Just silence the compiler (and write a thorough note in the
documentation) - Create and call a separate “Simplified” method which
returns another object (creating extra objects) - Do optimizations which return the same object
in init(e.g. [[[x]+1]+1] -> [[x]+2]), but require a “simplified”
method for the [2+2]=[4] case. - ???
Any thoughts or advice is appreciated.
Instead of doing this work in init, maybe you should just have a convenience method that sets up the un-simplified expression, then goes through and simplifies it and returns the simplified one. Or you could do this as a method on the object itself, e.g.
This could return
selfif it’s already simplified, or construct a new simplified version if not. That way you can still alloc/init your objects as you’re doing now, and then simplify them afterwards. You could even make a convenience constructor that does both at once: