18

Is this code correct

@implementation Vehicle
+(id) vehicleWithColor:(NSColor*)color {
    id newInstance = [[[self class] alloc] init]; // PERFECT, the class is // dynamically identified
    [newInstance setColor:color];
    return [newInstance autorelease];
}
@end

Why use [self class]

I thought self already points to the class on static methods (the ones with +)

Sherm Pendley
  • 13,556
  • 3
  • 45
  • 57
user4951
  • 32,206
  • 53
  • 172
  • 282

2 Answers2

19

It's to support subclassing. If you hard-coded the class name, as in [[Vehicle alloc] init], then a subclass of Vehicle would have to override +vehicleWithColor: to make it do the right thing. With [self class], you could create a subclass HarleyDavidson, and [HarleyDavidson vehicleWithColor:[NSColor blackColor]] would do the right thing automatically, creating an instance of HarleyDavidson instead of an instance of Vehicle.

(Edit:)

See Joe's comment below concerning self vs. [self class] in class methods - In class methods, it doesn't make a difference. But there is a situation where it can. Classes can respond to instance methods that are defined in a root class - -class itself is just such a method, defined as an instance method in the NSObject protocol. So if you extend a root class such as (for example) NSObject by adding an instance method, that method should always use [self class] if it needs to refer to its own Class object.

Sherm Pendley
  • 13,556
  • 3
  • 45
  • 57
  • 3
    Also to note `[self class]` works but is not necessary as `self` is the class in a static method. `[[self alloc] init]` will save a step. – Joe Apr 14 '11 at 17:51
  • 1
    @Joe - Reading the question again, I think `self` vs. `[self class]` may actually be what Jim is asking about, not hard-coded class names. – Sherm Pendley Apr 14 '11 at 17:56
  • 1
    Your actually right I think I answered him by commenting on your post :) Take your +4 and RUN! – Joe Apr 14 '11 at 18:02
  • Say I have an instance method. Say the method call a class method. -void InstanceMethod {[self ClassMethod]}. Within the class method, will self refer to the class or to the instance? – user4951 Apr 15 '11 at 10:55
  • @Jim You can't call a class method like that, since self refers to the instance, not the class. – Daniel Dickison Apr 15 '11 at 13:59
  • @Jim - In an instance method, `self` is an instance, so you need to use `[self class]` to call a class method: `[[self class] classMethod]`. – Sherm Pendley Apr 15 '11 at 14:11
  • Oh so still there is no point in using [self class] in a class method then. Any place where there is? – user4951 Apr 17 '11 at 08:48
  • @Jim You use `[self class]` when you want to call a class method on your own class from an instance method. But there's no point in using it to call a class method from another class method. (Note that this is different from Java, where you can use the dot syntax to call static methods on the class of an object instance, e.g. `anInstance.staticMethod()`.) – Daniel Dickison Apr 18 '11 at 19:48
  • For anyone still confused as to what Daniel is saying, try it for yourself. Use self in an instance method to call a class method (class method of the same class, otherwise you wouldn't be using self would you!). You will get an error. But self.class to call a class method from a class method (both being from the same class) is unnecessary. Self will work fine. – pnizzle Jul 15 '13 at 05:57
  • Note that you can also write `[[self.class alloc] init...]` as an alternative to writing `[[[self class] alloc] init...]`, because `-[NSObject class]` is, for an intents and purposes, a property of NSObject. Objective-C doesn't care if you use property notation for methods which take no argument, and in this case (and many others) it's syntactically cleaner to pretend that `class` is a property. Interestingly, `superclass` *is* officially a property of NSObject. – Todd Lehman May 30 '17 at 19:18
19

You're right: [self class] is unnecessary in a class method (it's more commonly called that in Objective-C rather than "static" method), because self is already a class, and [self class] returns itself.

But it gets a bit more interesting. In Objective-C, class objects are technically instances of metaclasses. So [self class] in a class method ought to return the metaclass instead of the class itself. But for practical purposes, Objective-C hides the metaclass so it handles this case specially.

Some good reading on this topic:

Daniel Dickison
  • 21,832
  • 13
  • 69
  • 89
  • The class is the metaclass. The other class that's not the meta class is the instance. Hmm.... I am confused my self. I'll read that first. – user4951 Apr 15 '11 at 10:44
  • the meta class is an instance of some super class. In a sense that instance is the class. [self class] ought to return the metaclass super class you mean? But it's still just self right? – user4951 Apr 17 '11 at 08:49
  • Ah I see, [self class] should return the metaclass. It doesn't. It return itself. Funny – user4951 Apr 25 '11 at 12:24
  • @Jim - yup you got. It's hard to explain metaclasses, and (in my experience) rarely useful to actually mess with, but it can be fun to play around with it. Common Lisp and Python have much more accessible and configurable metaobject protocols. (See http://en.wikipedia.org/wiki/Metaclass) – Daniel Dickison Apr 25 '11 at 14:53
  • This one has explanation of metaclass. The class of a class should be a a super class namely the classes of all classes yet doesn't work that way. +1 for pointint out. – user4951 Dec 06 '11 at 03:06
  • Hmmm... Helpful post w/ some good links. After reading the links, I think I see why [self class] doesn't return the metaclass: the Class object implements the -class method simply by always returning itself, since it is a Class. This would be what happens when you call [self class] in a static method, but also when you call something like [NSString class] (NSString would be the Class object, and obviously we want that same object to be returned). Its only for objects that don't inherit from Class, that implement the -class method by returning the value of the isa var. Am I right? – Richard Venable Apr 20 '12 at 20:10
  • "So [self class] in a class method ought to return the metaclass instead of the class itself." No. It calls the `+class` class method (defined in `NSObject`) instead of the `-class` instance method. `+class` overrides `-class` for class objects. `+class` simply returns the thing it's called on instead of the thing's class – user102008 May 31 '12 at 05:26
  • @Jim Thio: The class and metaclass are separate. `[self class]` does not return the metaclass because it is calling `+class` instead of `-class`. There is not one metaclass; each class has a separate metaclass. You can get the metaclass with `object_getClass()` – user102008 May 31 '12 at 05:27
  • @RichardVenable: Basically, it's all explained by the existence of `+class` and `-class`. There is nothing special with class objects or how the implement anything. – user102008 May 31 '12 at 05:32
  • [self class] in class object should have returned the metaclass, which is of course not what we want. Interesting :) +1 for pointing that out. So yes there is no use to call [self class] – user4951 May 31 '12 at 06:50