I am from Actionscript Background. In Actionscript Class Method can access only Class Methods and Class properties.
But In Objective C,
How Class method gameResultAll can access Instance Method initFromPlist
+(NSMutableArray *)gameResultAll://Class Method
-(id)initFromPlist:(id)plist;//Instance Method
NSMutableArray *gameResults = [GameResult gameResultAll]; // (returns GameResult array)
Why [self init] method is called instead of [super init] to create an instance from class method.
Thanks in advance.
#import "GameResult.h"
#implementation GameResult
#define GAME_RESULT_KEY #"gameresult_key"
#define SCORE_KEY #"score"
+(NSMutableArray *)gameResultAll
{
NSMutableArray *resultArray = [[NSMutableArray alloc] init];
for (id plist in [[[[NSUserDefaults standardUserDefaults] dictionaryForKey:GAME_RESULT_KEY] mutableCopy] allValues])
{
GameResult *gameResult = [[GameResult alloc] initFromPlist:plist];
[resultArray addObject:gameResult];
}
return resultArray;
}
//Designated initialiser
-(id)initFromPlist:(id)plist
{
self = [self init];
if(self)
{
if([plist isKindOfClass:[NSDictionary class]])
{
NSDictionary *resultDictionary = (NSDictionary*)plist;
_score = (int)resultDictionary[SCORE_KEY];
}
}
return self;
}
You asked:
How Class method gameResultAll can access Instance Method initFromPlist
It can access that method because you used the alloc method, which creates an instance of GameResult. Now that you have an instance, you can use instance methods in conjunction with this instance.
By the way, this is a very common pattern, a "convenience" class method that allocates an instance of an object (with alloc) and initializes the object (with init or some permutation of that). Or, as in this case, it can create an array of these objects.
You then go on to ask:
Why [self init] method is called instead of [super init] to create an instance from class method.
I can understand the confusion, but there is an important, yet subtle distinction in the behavior of these two.
Imagine this scenario:
At some future date, you subclass GameResult, e.g. ArcadeGameResult;
You implemented an init method for ArcadeGameResult that initializes some properties unique to this subclass; and
You happen to initialize a ArcadeGameResult instance like so:
ArcadeGameResult *agr = [[ArcadeGameResult alloc] initFromPlist:plist];
Because the initFromPlist uses [self init], it means that the the initFromPlist method of GameResult will end up calling the init method of the object (which in this example, is actually a ArcadeGameResult object). But if initFromPlist in GameResult called [super init] instead, it would not have called ArcadeGameResult's init method and thus initFromPlist would be problematic if ever used in conjunction with a subclass.
Bottom line, unless the method you're calling is the exact same method signature, it's safer to call the self rendition rather than the super rendition. It's a little more flexible in case you ever decide to subclass in the future.
There is a corollary to the counsel. When calling class methods from an instance method, you should refer to [self class] rather than the class name. So, imagine your GameResult class had a class method:
+ (void)someClassMethod
{
// do something
}
If you had some GameResult instance method that was going to avail itself of this method, you might be tempted to write:
- (void)someInstanceMethod
{
// do some stuff
[GameResult someClassMethod];
}
But that's not a good idea. You would instead use the following:
- (void)someInstanceMethod
{
// do some stuff
[[self class] someClassMethod];
}
They look very similar, but the latter lets you implement a someClassMethod in a subclass, and this instance method will still work. If you use the former construct, the subclassed class method wouldn't be called by someInstanceMethod.
These are subtle issues, and probably not critical for your current code sample. But hopefully it illuminates the choice of [self init] versus [super init] in this situation.
In Actionscript Class Method can access only Class Methods and Class properties.
That's not different in Objective-C either (because nothing else would make sense), so:
How Class method GameResultAll can access Instance Method initFromPlist
Only through a valid instance.
Why [self init] method is called instead of [self super] to create an instance from class method.
Because the latter is a syntax error, perhaps? Read a basic Objective-C tutorial.
Related
I'm having trouble understanding the use of [[self alloc] init] when writing factory methods. I understand that factory methods are convenience methods to create instances of a class, and that they do the alloc, init, and autorelease for you. I can see how this is formed, for example in the declaration of an NSArray property with the factory method arrayWithArray:, or array, etc. called on it to set it up.
I can obviously see how this is different to an outright (explicit) call to alloc and init.
My issue with this is that I don't understand factory methods at a deeper level. I came across an explanation online that said instead of calling alloc and init explicitly, a class factory method could be used to basically encapsulate something like this:
+(instancetype)createWithString:(NSString *)string
{
return [[self alloc] initWithString:string];
}
But how do instancetype and [self alloc] effectively allow for subclasses to make use of the class factory method?
instancetype is a keyword that says "the return type of this method is the type of the class that this method was called on" (or a subclass). So, if you call [Baseclass createWithString:], the return type is Baseclass *. However, let's say you create a subclass that does not override this method. If you call [Subclass createWithString:], the return type is Subclass * (not Baseclass *).
When a class receives a message, self points to the Class object. So when calling [Baseclass createWithString:], self will point to the Baseclass object. However, when calling [Subclass createWithString:], self will point to Subclass instead, so if Subclass defines its own alloc or initWithString: methods (that is, it overrides them) its versions will be called instead.
I'm quite a newbie in Objective C, though I have some background in Java reflection.
Here, I have a classic class method findAll that find all the domain objects from the database. The class Univers directly inherits from DomainObject
#interface DomainObject : NSObject
- (NSString *) execute : (NSString*) method withJson:(NSString*)json;
+ (NSString*)findAll: (NSString*)json;
#end
#implementation DomainObject
- (NSString *) execute: (NSString*) method withJson:(NSString*)json{
method = [NSString stringWithFormat:#"%#%#", method, #":"];
//method is 'findAll:'
NSString* result = [ self performSelector:
NSSelectorFromString(method) withObject:json];// Error here
return result;
}
#end
The code was working when findAll was NOT a class method (ie -findAll declaration), but now I have the error : NSInvalidArgumentException -[Univers findAll:]
It clearly seems that the runtime is looking for an instance method.
Any idea to find my class method ?
Instead of calling
NSString* result = [self performSelector:NSSelectorFromString(method) withObject:json];
you need to call
NSString* result = [[self class] performSelector:NSSelectorFromString(method) withObject:json];
for class methods.
After all it's the object instance's class that supposed to be calling the method, not the instance itself.
Short explanation: NSObject implements - (Class)class; (not to be mistaken with + (Class)class of similar effect, which NSObject implements, too!) which returns the Class object of your instance object. Keep in mind that in Objective-C in addition to plain instance objects, Classes are actual objects, too: objects of type Class, that is (vs. id, NSObject, …).
See the documentation for the -class method here.
Btw, you should probably wrap your method call into an conditional block to prevent exceptions caused by calls to missing methods.
SEL selector = NSSelectorFromString(method);
if ([[self class] respondsToSelector:selector]) {
NSString* result = [[self class] performSelector:selector withObject:json];
}
In general it's a common pattern in Objective-C to call an object's class method by receiving the class object via [object class].
Consider this case of a class called Foo implementing a convenience method for returning an autporeleased instance of itself (to be called via: Foo *newFoo = [Foo foo];):
While it would certainly be possible to implement said method like this (after all we know the object's class name, right?):
+ (id)foo {
return [[[Foo alloc] init] autorelease];
}
the correct way is this:
+ (id)foo {
return [[[self alloc] init] autorelease];
}
As the first one would cause problems with polymorphism in subclasses (Such as a subclass called FooBar, for which it should clearly be [FooBar alloc] …, not [Foo alloc] …. Luckily [[self class] alloc] solves this dynamically).
While this is clearly not the right place for a thorough explanation of this (rather offtopic one might say) it's certainly worth noting/warning about, imho.
As a part of my transition process from C++ to Objective-C, I intensively read book Cocoa and Objective C Up and Running.
In one of the book code examples, there is a line that does not make sense to me with my current level of knowledge:
It is a declaration of class method + (Photo*) photo;.
Could anybody explain me the reason, please, why the author had decided for the method (Photo*) photo; to declare it as a class method instead of instance method?
I have studiet the theory, that the instane method is something like a class member function and that class method is something like static function in C++. But this still does not answer my question.
Here is the declaration code:
#import <Foundation/Foundation.h>
#interface Photo : NSObject{
NSString* caption;
NSString* photographer;
}
+ (Photo*) photo;
- (NSString*) caption;
- (NSString*) photographer;
- (void) setCaption: (NSString*)input;
- (void) setPhotographer: (NSString*)input;
#end
The implementation code follows:
#import "Photo.h"
#implementation Photo
- (id)init
{
self = [super init];
if (self) {
[self setCaption:#"Default Caption"];
[self setPhotographer:#"Default Photographer"];
}
return self;
}
+ (Photo*) photo {
Photo* newPhoto = [[Photo alloc] init];
return [newPhoto autorelease];
}
- (NSString*) caption {
return caption;
}
- (NSString*) photographer {
return photographer;
}
- (void) setCaption:(NSString *)input {
[caption autorelease];
caption = [input retain];
}
- (void) setPhotographer: (NSString *)input {
[photographer autorelease];
photographer = [input retain];
}
- (void)dealloc
{
[self setCaption:nil];
[self setPhotographer:nil];
[super dealloc];
}
#end
The + (Photo*) photo method is a Factory Method that encapsulates the details of creating an object of the Photo class.
A Factory Method enforces
encapsulation, and allows an object to
be requested without inextricable
coupling to the act of creation.
In this particular example the information being hidden by the factory method is memory management, since the client does not need to worry about releasing the returned object.
It is a common practice in Objective-C APIs to provide factory methods in classes that return autoreleased objects of that same classes. These methods must not contain any of the words “alloc”, “new”, “copy”, or “mutableCopy”, which, according to the convention, indicates that the caller doesn't own the returned object, i.e. it doesn't have to be explicitly released.
Related resources:
Memory Management Rules
Meta answer:
One issue; that method should be
declared as returning id and should
return [[[self alloc] init]
autorelease]; (one line or two,
doesn't matter -- just should refer to
the Class directly). As it is, Photo
is gonna be a pain to subclass.
Expanding -- given this:
+ (Photo*) photo {
Photo* newPhoto = [[Photo alloc] init];
return [newPhoto autorelease];
}
If the class were subclassed, this factory method would not work without being overridden to do pretty much the same thing. However, since Objective-C doesn't support co-variance and contra-variance, there would be no way to declare the subclass's implementation of +photo to return an instance of the subclass without also running a significant risk of compiler warnings. Alternatively, you could down-cast the return value to the more specific class, but that is rife with fragility.
Instead, do this:
+ (id) photo {
id newPhoto = [[self alloc] init];
return [newPhoto autorelease];
}
This fixes both issues:
since it uses self, it'll instantiate an instance of whatever class it is implemented on, including subclasses of Photo.
since it returns id, callers can do both of the following without issue:
Photo *p = [Photo photo];
SubclassOfPhoto *s = [SubclassOfPhoto photo];
In this scenario, photo is a convenience method, which returns you an autoreleased instance of the class.
Since the purpose of photo is to give you an instance, it wouldn't make sense to make it an instance method which would require you to already have an instance.
If you're familiar with Factory Methods, the photo method is similar to that.
+photo is like a constructor. You need a way to get an object to send instance methods to, and this gives you an autoreleased one.
It is equivalent to a static method, as you say. In this case (and all cases of [ClassName className] methods) it's basically a factory method. You're asking the class to construct an instance of itself and pass it back. All such methods should return an autoreleased object.
You can safely ignore methods like that if you want - there will usually be an alloc+init equivalent, but it's often more convenient to use the class method, especially if you're creating a throaway object and don't want to retain it.
Finally, you'll sometimes find classes which require you to use the class method, as they'll hide some clever logic wherein an instance of another class is actually returned. You'll sometimes hear these described as 'class clusters'.
Could anybody explain me the reason, please, why the author had decided for the method (Photo*) photo; to declare it as a class method instead of instance method?
It's basically a wrapper of the constructor litany. Note the source:
+ (Photo*) photo {
Photo* newPhoto = [[Photo alloc] init];
return [newPhoto autorelease];
}
Allocate a new Photo, initialize it, mark it autorelease, and return it. Since it creates the object, there is no object yet to operate upon, ergo this needs to be a class method.
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 +)
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:
http://www.sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html
Inheritance diagram: http://www.sealiesoftware.com/blog/class%20diagram.pdf
http://cocoawithlove.com/2010/01/what-is-meta-class-in-objective-c.html
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.
I'm new with objective c for the iphone.
I'm writing a custom class, then, should I write my own +alloc, +init methods?
I believe that: the +alloc will just call [thing alloc]; and the +init will perform something like: [thing setValue:X];
is there a "default" +alloc and +init methods?
if yes, what should I wait for the default +alloc and +init?, let's say i have a NSMutableDictionary*
i.e.
#interface class1 : NSObject {
NSString *test;
NSMutableDictionary *map;
}
thanks
You generally don't need to write your own +alloc method.
For your example, you might have an -init that looks like:
- (id)init {
self = [super init];
if (self) {
map = [[NSMutableDictionary dictionary] retain];
}
return self;
}
Note that you first call the superclass -init, and check that it worked, before initializing your own variables.
You should NEVER override alloc.
As for init, which is an instance method, by the way, yes that would be the place where you'd probably want to set up your variables.