11

We know that in Objective-C there are two main root classes: NSObject and NSProxy. There are other roots (mainly for private and legacy purposes) like Object, and NSLeafProxy.

Defining a new root is fairly trivial:

@interface DDRoot <NSObject>

@end

@implementation DDRoot

//implement the methods required by <NSObject>

@end

My question is: why would you ever want to define a new root class? Is there some use-case where it's necessary?

Michael0x2a
  • 58,192
  • 30
  • 175
  • 224
Dave DeLong
  • 242,470
  • 58
  • 448
  • 498

4 Answers4

12

There are two primary reasons to create a new root class; proxying & a new object model.

When proxying, it can be useful to implement a new root class such that you can basically handle any and all of the class/object's behaviors in a custom fashion. See NSProxy.

The Objective-C runtime is flexible enough that you can support a new object model quite easily (where easily discounts the inherent complexity of creating such a beast in the first place). Actually, many of the behaviors that are considered inherent to the runtime -- KVC, KVO, etc.. -- are implemented as a part of the NSObject class itself.

I know of at least one company that -- as of about 8 years ago, at least -- had implemented their own object model as a part of building their ~500k LOC financial analysis engine.

The key, though, is that if you go this route, you don't try to make your classes interact with Foundation/CF/AppKit/UIKit, etc. If you need that, just subclass NSObject already!

It is interesting to note that NSManagedObject is effectively a root class in that it does some pretty seriously custom stuff, but it is a subclass of NSObject so subclasses of NSManagedObject are inter-operable with the rest of the system.

Felixyz
  • 19,053
  • 14
  • 65
  • 60
bbum
  • 162,346
  • 23
  • 271
  • 359
8

As far as I can tell, there should be no reason for creating your own root class, because short of implementing all of the NSObject protocol methods yourself, you're going to be missing out on a lot of functionality, and going to be making a lot of calls to the Objective-C runtime that should essentially be done for you.

Unless you really had to implement the protocol differently from the default (NSProxy is a special case that does have to), you shouldn't need to make your own root class. I mean, you'd have to be writing a class that cannot fundamentally be represented by NSObject and the protocol as implemented by Apple, and in that case, why are you even writing it in Objective-C?

That's what I think. Maybe someone can come up for a creative use for it.

(People researching the topic should go look at the NSObject Class Reference, NSObject Protocol Reference, 'Core Competencies: Root Class' document, and the 'Root Class' section of the Fundamentals Guide: Cocoa Objects document.)

Felixyz
  • 19,053
  • 14
  • 65
  • 60
Itai Ferber
  • 28,308
  • 5
  • 77
  • 83
  • I think your point about wanting fundamentally different behavior is the defining reason. Most of the methods in `` seem related to memory management, so you'd probably want to use a new root class if you wanted to do something absurdly bizarre with that. – Dave DeLong Nov 28 '10 at 06:40
  • I can think of one possible use, but there are probably better ways to do it, and there isn't really any need for it. You could define a new framework that obfuscates the calls and uses it's own runtime to decode the protected parts of the program. But again, WHY? – Rich Jan 19 '11 at 08:52
5

Objective-C and Cocoa are separate things, and in principle it’s possible to define entirely new application frameworks that don’t use Foundation. The financial analysis people bbum mentioned are a practical example, and I believe they’re still around.

Another use is to make a proxy that’s more minimal than NSProxy, as Mike Ash does here.

Oh, and the private NSInvocationBuilder is a root class, presumably for the same reasons as Mike’s proxy. Capturing invocations for later use is something one might want to recreate.

Jens Ayton
  • 14,532
  • 3
  • 33
  • 47
  • I recently found myself implementing a root class for another reason: I wanted NSZombie-style behaviour for objects that used custom memory management (don't ask). To ensure that _all_ messages would result in a zombie crash, the base zombie class was a root class with no methods except -forwardingTargetForSelector:. – Jens Ayton Dec 08 '13 at 13:01
1

Companies like the OmniGroup have defined a version of NSObject to use as their own base class for everything.

It's essentially a subclass of NSObject with some debug stuff. Other than that, it's usually a terrible idea to fight the framework.

Find Omni's code here: https://github.com/omnigroup/OmniGroup

Dexter
  • 5,666
  • 6
  • 33
  • 45