I've recently needed to create my own type similar to NSRect that has an anchor point (essentially an NSRect with another NSPoint in it).
After some research I found that I was actually probably better off to just make this a class (as in NSObject subclass), rather than using struct. Why then has Apple make these types structs, not classes? It seems like it would have many benefits, such as not having to wrap them in NSValues, not have to use C functions to interact with them, etc.
I'm sure they'd have a reason. Is it simply the slightly less memory usage? Is it just historical? Or have I missed something bigger?
Each programming paradigm has its own pros and cons, and object-oriented programming (OOP) in not an exception.
All major benefits from having classes (that is, writing in an object-oriented style) is encapsulation, polymorphism and inheritance.
If we declare such simple units as Rect or Point a class, we won't use anything from that list, but we'll bring all the disadvantages that OOP has, including implicit mutability, more complex memory management, pointer references, implicit actors, broken encapsulation (with setters/getters), etc. And I don't list here hundreds of anti-patterns that do exist in OOP.
I doubt that the choice of structs for Rect and Point in Cocoa was justified by C legacy, first of all because Objective-C supported classes from the outset, and secondly because the brand new Swift language does not have this legacy, but still almost all standard types and containers are declared in its standard library as structures, not classes.
In general, if you don't need encapsulation, polymorphism and inheritance - you should consider declaring your new entity as a struct and avoid OOP whenever possible.
The overriding reason is performance - all of Cocoa's performance-critical APIs (graphics, audio) tend to use C structs and functions for this sort of purpose.
The reasons are that these can much more easily be optimised by the C-compiler. C functions can be called more cheaply than methods, and they can be inlined automatically by the compiler, removing the function call overhead altogether. C structs are allocated on the stack instead of the heap, which means that processing can mostly be done in registers or low-level CPU caches instead of calling out to main memory, which is hundreds of times slower.
Cocoa methods are dynamically dispatched. They might be overridden by a subclass or swizzling, so the compiler cannot inline them because it can't be sure what they will do until they are executed at runtime. Cocoa classes are allocated on the heap, so they must be allocated/deallocated, and there's all the other overhead such as reference counting. They are also likely to end up spread out in memory, which means that there may be significant performance losses due to the memory blocks they reside in having to be paged in and out of cache.
Also a good point is operation speed. These points and rects are mostly used to render something and thus need faster operating than ever. Instead of allocating an object, which will trigger recursive init
, spending a lot of bytes and cpu cycles for undercover work, it's just faster to say "here I have 16 bytes which is 2 CGFloats of NSPoint struct". This also makes a lot of sence when delegating work to a GPU, which don't know anything about OOP and methods of your objects, but need to draw a lot on screen without glitches.
Why then has Apple make these types structs, not classes?
For performance reasons, as these entities are frequently used, frequently processed and small. And the overhead of having them encapsulated in objects is not justified by the advantages of them being objects.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With