What is the functionality of method called class in objective-C - objective-c

Hi I was studying about initialize class method in objective-C. I came across this code which confused me
+ (void)initialize {
if (self == [Car class]) // what is the use of method class??
{
// Makes sure this isn't executed more than once
_defaultModel = #"Nissan Versa"; // initializing the static variable _defaultModel
}
}
Here I know that we're using if (self == [Car class]) to check whether the self is referring to class itself or not. But what is the functionality of method class in [Car class] . I'm a newbie and I'm learning objective-C from couple of weeks when I searched for answers for this question all i got is difference b/w class methods and instance methods which I know. So please tell me what is the functionality of method class. Thanks in advance .

Two things to note here.
First, as you say the code is "using if (self == [Car class]) to check whether the self is referring to class itself or not". The method class returns the class object for Car, and self will be the same object if initialize is being called on Car.
Second, how could the class method initialize of Car be called on anything other than Car itself - it belongs to the class after all?
The answer to this lies in inheritance. The +initialize of Car will be called once before any instance of Car is created. However it will be also called once for every subclass of Car before the first instance of that subclass is created. E.g. if you have a class:
#interface Volvo : Car
...
#end
Then if Volvo has an +initialize then it will be called before the first instance of Volvo is created and Car's +initialize will also be called before the first instance of Volvo is created. This is why you will often see class initializers with an if statement to check for self being the class itself - it ensures the code is only executed once and not once per subclass as well.
HTH

[NSObject class]
Returns the class type of the object. See Apple's API
(By the way as a side note it's always good to google for the API before asking questions here)

There are two methods named class in Cocoa: the class method +[NSObject class], and the instance method -[NSObject class]. They do very different things, so do not get them mixed up. The former overrides the latter for class objects.
Here you are asking about the class method +[NSObject class], so that's what we will talk about. This method simply returns the object (class object) that it is called on, similar to -[NSObject self]. In fact, [Car class] can also be written as [Car self].
So why do we use a method that simply returns what it was called on? Why not just use the thing it's called on directly? This is due to a peculiarity in Objective-C syntax. In Objective-C, a class name like Car is not a valid expression (don't know why; the gods just made it that way). So we cannot just directly write self == Car, even though that's what we're really trying to say.
On the other hand, Objective-C has a special case for the message sending syntax [ ], where if the thing on the left side is a class name, the message is sent to the class object. So the "work-around" to get the class object for a class is to use the [ ] syntax to call a dummy "return self" method on it. In the Cocoa/GNUStep/OpenStep framework, there are two methods that can do this, +class, and -self. By convention, +class is used (which is really unfortunate, due to confusion with -class). After a while, you'll just get used to seeing [SomeClass class] and interpreting it as the SomeClass class object, whereas [some_obj class] gets the class of some_obj if it is not a class object.
(Note: In Smalltalk, which is where Objective-C inherited much of its stuff from, a class name is the expression for a class. So something like self == Car would be the correct way to write it. And the class method in Smalltalk always gets the class of the object, regardless of whether it's a class object or not.)

Related

Why can't I use the classname instead of self in objective c

It's just something which is not logical for me. Sure it's useful to call methods within in a class by the self-keyword. But why isn't it possible calling it by the own classname??
e.g.
[MyClassWhereIAmActuallyIn anyRandomMethod]; instead of [self anyRandomMethod];
Because that has a different meaning.
[self someMethod]
sends someMethod to the object, whose reference is stored in the (slightly magic) variable self.
[SomeClass someMethod]
sends someMethod to the class object (yes, classes are objects, too), which contains the meta-information for class SomeClass.
Two different objects ("receivers"). Also note, that there are class methods in Objective-C (i.e., you can take advantage of the fact, that classes are objects, and define new methods for them). Observe:
#interface SomeClass
- (void) someMethod;
+ (void) someMethod;
#end
These are completely different methods, intended for completely different receivers. The method tagged with - is an instance method (will be used, e.g., with self). The method tagged with + is a class method (and will be used with the class object).
You can call class method ('+') like that. Self is a pointer to an instance of your class in instance methods ('-'), self points to the singleton Class-object when you are in class methods ('+').
In OOP this is the difference between the class object and an instance of that class object. When you create a method, you specify whether it is a class method (+) or an instance method (-). Once the method is defined you need to call it in the appropriate way (on the class object or on an instance of that class).

Can pointers of one class contain extended classes without problems?

I am newish to Objective-C. I am trying to determine if having a pointer for one class, then assigning an extended class to that pointer instead, will cause problems. For instance if ClassB extends ClassA, and I do this:
ClassA *foo = [[ClassB alloc] init];
Will this cause problems somewhere down the line? I know that Xcode seems to be okay with it, but that doesn't mean it is okay.
Yes, that's called polymorphism, you can do it without problems.
However since in Objective-C the message dispatching is dynamic, if the class B contains an overridden method, this one will be executed. This is often used when you know you'll receive an object of a class that inherits from a known base class, but you don't know which one. You can turn this to your advantage.

Is it an acceptable pattern for an init method to return an object of a different type?

I'm working on bugfixes for some existing objective-c code and came across something I thought strange:
#interface ClassA : UIView
...
static ClassA* oldSelf = nil;
#implementation
- (id)initWithFrame:(CGRect)frame {
oldSelf = self;
self = [[ClassB alloc] initWithFrame:(CGRect)frame]; // xcode warns: Incompatible pointer types assigning to "ClassA *" from "ClassB *"
// ^^^^^^ Is this ok?
[oldSelf release];
return self;
}
#interface ClassB : UIView
...
#implementation
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
return self;
}
This whole thing is wrapped up into a static library. The public gets the lib.a file and ClassA.h
In code using the library, This occurs:
#import "ClassA.h"
...
// useage
ClassA *myA = [[ClassA alloc] initiWithFrame:CGRectMake(0,0,100,100)];
...
So we got an initializer for ClassA that actually returns an unrelated class. ClassA and ClassB respond to the same messages so it compiles and runs. Seems like ClassA is being used to obscure some features exposed in ClassB?
I'm curious if this is acceptable behavior, and if it's a known pattern, what is it called? Are there any side effects to this setup?
=========================================================
Thanks for everyone's answers! I think I've got it... in short, not a normal pattern, and not exactly a good idea
Kind of like a "class cluster"(abstract factory), but not quite, because a common abstract class should be returned. And since the code doesn't seem to ever intend to return anything but a ClassB object, probably not what the original author was thinking.
More like a proxy, but implemented wrong. ClassA should hold a private instance of ClassB and pass messages between the two.
=========================================================
Edited: added "oldSelf" parts...
Edited: added static library details...
Edited: added a blurb about the accepted answer...
The major disadvantage I see here is: a user of ClassA would expect that an object he just created via [[ClassA alloc] initWithFrame:...] returns YES for [object isKindOfClass:[ClassA class].
This might also lead to errors when using things like NSInvocation, because the wrong class would be used to determine the method signature, though I am not sure about that.
Due to Objective-Cs dynamic nature, this will, as you described, work, but may be confusing to use and i would strongly discourage anyone from using this pattern.
As pilavdzice said, the "right" alternative to this would be to have both ClassAand ClassB inherit from another class (an abstact superclass) which then in its initializer decides what concrete subclass to use. Good examples of this pattern, called class clusters, are NSString, NSArray and NSDictionary which all return objects of various subclasses based on how you initialize them, which is also the reason you can not subclass those directly without some effort.
It's not an unreasonable thing to do in all cases, but it's hard to say whether it's a good idea in the situation you describe. Two examples where it might be fine:
The initializer returns an instance of a more specialized subclass. For example, you might choose different implementations of a data structure depending on the number of items being stored.
The initializer returns some sort of proxy object.
Your code does seem a bit odd. At the very least, I'd expect to see a cast as a signal (both to the compiler and to future programmers) that the author knew what he was doing. A comment explaining the reason for returning a different type of object wouldn't hurt, either. Ideally, ClassB should be a subclass of ClassA since it's expected to provide the same interface.
Class clusters are implemented in this way, sort-of. A related technique, isa-swizzling can be used to implement a sort of state machine. It does require the same ivar layout to work. In terms of side effects, I believe that it may break KVO; but someone may correct me on that point.
It's certainly not common in user code to return an unrelated class, however it is common in some of Apple's frameworks to return a more specific version of a class with the same public interface.
Apple's Cocoa Fundamentals discusses in some amount of detail the fact that objects such as NSArray and NSNumber may return a different object than the class you are asking for.
That isn't a pattern I know of.
If I am understanding this correctly, the normal way to do this would be to have both classes inherit from the same abstract base class.
As #alan duncun notes, this technique is called a class cluster and is somewhat common. But your implementation is slightly incorrect. You should never return a incompatible type. In your example, ClassB should inherit from ClassA.
Well this is somewhat how NSScanner is implemented.
This way the inner class is not exposed and can not be misused. ClassB can not be initialized somewhere else other than in the implementation file of ClassA.
This makes sense if you have multiple inner classes and your initializer somehow decides which class is actually needed.
I don't see any advantages if you only use one inner class.

Objective-C initializers and overriding self

I have a question about writing your own init methods in objective-c. I've read a few different books and have seen a couple of ways to do it but the consensus is the right way to do it is like this:
- (id)init
{
self = [super init];
if(self!=nil)
{
}
return self;
}
I'm a little confused about the line "self = [super init]". My understanding is that, there's no guarantee that [super init] will return the class that you expect it to. I think this is called "class clusters". But in the normal case, where it does return the class you expect it to, if I set self to point to a class that is returned to me, aren't I just saying that self is referring to an object of a different class rather than the class that I'm in the init method of?
To summarize, why set self to be the superclass vs the actual class I'm in?
From a blog I read:
The textbook reason is because [super
init] is permitted to do one of three
things:
1) Return its own receiver (the self
pointer doesn't change) with inherited
instance values initialized. 2) Return a
different object with inherited
instance values initialized. 3) Return
nil, indicating failure. In the first
case, the assignment has no effect on
self...
"The assignment has no effect on self" is what confuses me. Why does it have no effect? If I set something = to something else, shouldn't that have an effect?
There are different opinions on the proper way to write -init methods. There are two reasons that would make you think that self = [super init] is a good idea. (The assignment itself isn't anything special; Objective-C considers self to be a hidden parameter of the method, and you can reassign to parameters. The changed self only applies for the remainder of the method.)
Superclass -init returns instance of different class
As you suggested, some classes use the "class cluster" pattern. However, in the most common implementation of this pattern, it's the -alloc method on the base class that is likely to return an instance of a different class, and it's all the -init... methods on the placeholder class that are likely to return an instance of a different class. self = [super init] is not useful here.
Superclass -init returns a different instance of the same class
This is the reason that self = [super init] is recommended. Some classes have logic that allows -init to return a different instance than the one that it was called on. For example, some singleton classes in the Cocoa framework do this. But in almost every case, you need to know this behavior of the superclass in order to properly subclass it. Here's an argument by Wil Shipley that self = [super init] isn't actually very useful, because either [super init] returns self anyway, or the class you're subclassing is sufficiently complicated that reassigning self and then continuing with the initialization won't work anyway.
To summarize, why set self to be the superclass vs the actual class I'm in?
This is the Apple suggested way to do things, specifically due to the case of class clusters, as you say.
In general, you should not worry about the fact that self might be of a different class in the "normal" case.
self simply identifies the object you are, not the class (the class is actually a different object in the runtime). If you think of OO inheritance properties, it is at the same time an object of its class and of its superclass (if it is clear what I am trying to say). There is no contradiction in the "normal" case, since the value of self does not change.
Also, you can think of self as a special pointer to your object. In the cluster case, self can change, that is the reason why it can happen that its class change.
Hope this helps clarifying things. You will also find an interesting reading in this article by Wil Shipley.

Why send a class through +(Class)class before calling a class method?

I've been browsing Sketch, an example program they ship with Xcode, and I keep seeing things like this (not always though):
[[MyClass class] classMethod]
Now, since MyClass isn't an instance of the class, I would just do:
[MyClass classMethod]
As an experiment though, I was able to make a difference between the two above statements, by overriding + (Class)class and returning another class! If you ever want to do this, you would need the former version for it to work, so I can see that there could be a usage for this, but is there really?
It sounds like an awful idea tampering like this with +class, but please enlighten me if there is. Thanks!
To see some examples, check out the method -copy: in SKTGraphicsView.m in the Sketch program found in Developer/Examples/Sketch/.
In the case that you cited, I don't really see any good reason for calling +class. However, there is definitely a case for calling [[self class] doSomething] instead of [[MyClass class] doSomething]. In the first case, [self class] can return the correct result if the object has been subclassed. In the second case, you will always get the MyClass class object, which means that MySubClass could not effectively override the +doSomething class method.
There is no good reason for using +class in that case. +class simply returns the object (the class object) that it is called on, same as -self. In most cases, people use [SomeClass class] to get the class object for a class, because the name of a class is not an expression, and can only be used as the receiver in the message calling syntax as a special case. Therefore, in all other contexts, they use [SomeClass class] to get the class object as an expression (although [SomeClass self] would also work equally well).
In the case you showed, it is redundant, because it is the receiver of a message. I am guessing they did it out of habit or ignorance (they thought that you must always write [SomeClass class] to use the class).