How do I properly override a class method in an Objective-C in a subclass?

Up vote 5 down vote favorite 1 share g+ share fb share tw.

In the second chapter of his iOS Programming book, Joe Conway describes using 'self' in class methods in the event of subclassing. I understand this concept and have a question about the issue of subclassing. Background: We created a Possession class whose class method +randomPossession looks like this: +(id)randomPossession { NSArray *randomAdjectiveList = NSArray arrayWithObjects:@"Fluffy", @"Rusty", @"Shiny", nil; NSArray *randomNounList = NSArray arrayWithObjects:@"Bear", @"Spork", @"Mac", nil; unsigned long adjectiveIndex = rand() % randomAdjectiveList count; unsigned long nounIndex = rand() % randomNounList count; NSString *randomName = NSString stringWithFormat:@"%@ %@", randomAdjectiveList objectAtIndex:adjectiveIndex, randomNounList objectAtIndex:nounIndex; int randomValue = rand() % 100; NSString *randomSerialNumber = NSString stringWithFormat:@"%c%c%c%c%c", '0' + rand() % 10, 'A' + rand() % 10, '0' + rand() % 10, 'A' + rand() % 10, '0' + rand() % 10; Possession *newPossession = self alloc initWithPossessionName:randomName valueInDollars:randomValue serialNumber:randomSerialNumber; return newPossession autorelease; } I am aware that the return value should really be of type id such that id newPossession = ... I subclassed Possession and created a class called BallGlove that included a new iVar, brandName, an NSString * I overrode the +randomPossession in BallGlove as follows: +(id)randomPossession { BallGlove *myGlove = super randomPossession; NSArray *brandNames = NSArray arrayWithObjects:@"Rawlings", @"Mizuno", @"Wilson", nil; unsigned long randomNameIndex = rand() % brandNames count; myGlove setBrandName:brandNames objectAtIndex:randomNameIndex; NSLog(@"myGlove is of type class: %@", self class); return myGlove; } My question is this: Is the manner in which I overrode this class method appropriate and acceptable by the community (i.e.

Parallel the -init format by capturing the super implementation in a variable, manipulate the variable accordingly and then return it? My output shows that the object returned is an instance of BallGlove however, I was interested in the acceptable implementation. Thanks in advance.

Objective-c class methods overriding link|improve this question edited Dec 28 '11 at 17:29MadhavanRP1,0041210 asked Dec 28 '11 at 17:20Brian Palma1306.

It's technically ok. I'd propose an alternative, though. If you already have a designated public initializer on your base class (which you might want to create and call from that factory class method anyway), and then use that very initializer (or even a new one from your subclass) in your subclasses' class method.

It's not much more code, but in my opinion easier to follow and future-proof. The initializer might come handy as well at one point, but of course it's not a solution for every application.

RandomPossession in the base class in fact calls the designated initializer. The class method also creates "random" values for that initializer. If I do what I believe you are suggesting, I would have to replicate the code for those "random" values in the overridden class method (+randomPossession) as well as override the designated initializer to call a new initializer of class BallGlove, that would add my additional iVar info.

Why is overriding the class method as I proposed detrimental in a general sense? Can't it be likened to chaining initializers? – Brian Palma Dec 28 '11 at 19:51 I don't think it's overly ugly -it's just not a very common pattern.

The question itself is a good indicator for that. :) One thing that gets a bit vague with subclassing is the name of method, and good naming is one of the best things about objective-c. So in your case a method +randomBallGlove might be better than overriding.

– Eiko Dec 28 '11 at 20:41 You're suggesting that I instead create a class method named +randomBallGlove that includes the implementation of +randomPossession in addition to the custom implementation desired? Sounds good to me. What do you suggest for +randomPossession still being available to subclasses of Possession?

Override the method and have it throw an exception directing use of +randomBallGlove? Is this typically the normal protocol of such events? I know this example may be nonexistent in reality, I'm just learning and am curious as to accepted implementation in the event it happens.

Thanks for your help! – Brian Palma Dec 28 '11 at 21:14 Also, I know that it may not be a very common pattern but the mere acknowledgement of such an event by Big Nerd Ranch suggests there is some validity to my question. They aren't the be all, end all, however understanding implementation details like these allows expanded thought in future coding.

I really do appreciate the help! – Brian Palma Dec 28 '11 at 21:17 It's really an interesting topic, and I don't think there has been given many guidelines in that respect to the developer. Throwing exceptions feels wrong and artificial to me.

Obj-C always supports friendly code blocks that respect each other and work together. It doesn't go lengths to prohibit calling of a private method, for example. – Eiko Dec 28 '117 at 10:04.

The moment you override a class method you can decide to implement it with the help of the super implementation or without it. It is totally up to you. Overiding init is a completely differeent story, not only because it is an instance method but because it has a convention/contract associated with it.

Keep in mind that for instance methods the Liskov Subtitution principle should not be violated. Your overrided of the class method is perfectly fine, although I would consider overiding class methods a design smell. Although it's very well possible in Objective-C, it's not in other languages and that for a very good reason.

Polymorphism as a concept is better bound to instances that can be used as substitutes for each other, whereas using class methods breaks the concept (i.e. No real subtitution). It's clever, but not necessesarily intuitive and flexible.

Thanks for the reply. As I mentioned below, I'm not aware of any use of overriding a particular class method in a subclass, other than for less code in a convenience method. At this point, I have no intention of doing so.

I was merely curious as to the proper implementation if the situation arose. – Brian Palma Dec 28 '11 at 18:31 @BrianPalma: There are reasons to override class methods other than "convenience methods". For example, NSView's defaultMenu and requiresConstraintBasedLayout class methods exist just to be overridden.

– Chuck Dec 28 '11 at 19:03 @Chuck Sorry, I think I misspoke or am just too new! I mean "convenience methods" in terms of model objects. I understand that there are class methods in iOS and OS X that exist purely to be overridden and require super someClassMethodHere; – Brian Palma Dec 28 '11 at 19:14 @BrianPalma have a look at this answer stackoverflow.com/questions/5222083/… – MadhavanRP Dec 28 '11 at 19:21 @MadhavanRP Again, this does not answer the question.

I believe the question has been answered adequately by Chuck. I do in fact need the implementation of the superclass to properly set the variables in my subclass' inherited iVars. The question centered on proper implemenation.

Thanks. – Brian Palma Dec 28 '11 at 19:33.

Yep, that's a perfectly sensible way to do it. There's nothing particularly different between class methods and normal methods — just that one is performed by a class and the other is performed by an instance.

Yes, it is acceptable to do your initialization like that. In fact that is how it is done in most cases. I mean, that is the reason for inheriting from a super class in the first place.

You want stuff in addition to what is present in the super class. So, you insert code to whatever is specific to the inherited class and it should be done that way. I think how you want the BallGlove object initialized is also a factor in how you define your inherited method.

The question arises on calling the Possession init or calling the BallGlove init (Not that creating an instance of a class is the only place to use a class method). So it comes down to the logic of creating your objects i.e. How you well you are describing BallGlove object-are you making sure that your class method describes it in ways that fits the BallGlove object criteria and does not become generic Possession object.

My answer is that if you can implement it right, using a parallel line of class methods is acceptable. Also, it doesn't matter if you are returning of type Possession in your super class because, id can point to an object of any class type.

Thanks for the reply. That didn't really answer the question however. The question pertained to the format of overriding class methods.

Aside from the necessity of generating a convenience method for a subclass, I'm not sure of a reason for overriding the class method. As is such, I haven't seen anything on this yet. Are there are any examples verifying that the format I used is appropriate?

– Brian Palma Dec 28 '11 at 17:46 @BrianPalma I am sorry. Perhaps I did not answer it right. I don't really see why it is not acceptable to do it for class methods the same way as the initializers.

The way I figure it works is, class methods tend to call init methods, perform some code and return an autoreleased version which is what you are doing. I don't know if there are examples for verifying your format, but I also can't see any problems that could arise out of it. Let me check in some sample codes and get back to you.

– MadhavanRP Dec 28 '11 at 18:26.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions