Reputation: 845
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?
Upvotes: 17
Views: 2083
Reputation: 15827
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.
Upvotes: 3
Reputation: 40995
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.
Upvotes: 8
Reputation: 4728
If you've been playing with Objective-C for a while then you'll know that it is an OOP layer on top of coreFoundation, which is all structs and 'opaque types' (structs with secrets)..
For example, NSDictionary is really just a wrapper around the CFtype, CFDictionaryRef. Well, the things you're asking about here, size, point, rect, edgeInsets, etc. are just little data types which were determined to not warrant the upgrade. Primitives (int, double, bool, etc.) didn't get a (public) class to toll free bridge either. They got the NSNumber cluster, and these guys all got bunched together in the NSValue wrapper. You can write a concrete class to wrap a specific one if you need to...
Upvotes: 1
Reputation: 3196
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.
Upvotes: 4
Reputation: 3559
Because they need to be value types. Point or rectangle are not objects actually. They are just a bunch of data. They do not behave, they just store data you pass into them. You can write
CGRect frame = ...
UIView *view1 = [[UIView alloc] initWithFrame:frame];
frame.origin = ...
UIView *view2 = [[UIView alloc] initWithFrame:frame];
And it works fine. With reference types, which classes are, you will alter the frame of view1
while moving frame to another origin.
[myRect intersectsWithRect: otherRect]
definitely would be nice and actually Swift allows to do it. Value types like structs and enums can include methods in Swift, which makes it possible
Upvotes: 1
Reputation: 10791
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.
Upvotes: 12
Reputation: 314
You use structs when you want to pass things by value and classes when you want to pass them by reference.
Upvotes: 0
Reputation: 4122
I believe it has to do with the fact that each struct holds primitive types of data (in general floats and doubles) without any actions on their own (like functions or methods) so there was no need for something more complex like a fully featured class (no imports and no boilerplate code eg. initializers) and of course, as other colleagues mentioned, because Objective-C is a superset of C.
Upvotes: 2
Reputation: 1900
Generally a class is used when there are methods that operate on the data. If you have data only then simply use a struct. It seems there are not any useful methods to going along with point or rect so no need for a class.
Upvotes: 2