Objective-C method overriding/overloading confusion - objective-c

There seems to be some debate/disagreement on whether it is possible to 'overload' methods in Objective-C. Putting aside that it is impossible to define method overloading in Objective-C is terms equal to those of C++ (because of method signature syntax differences), I would ask in particular: Which of the following is allowed and which are not?
1) A class declaring/implementing both these methods:
- (void) doSomethingWithObject:(ClassA*) object;
- (void) doSomethingWithObject:(ClassB*) object;
2) A class declaring/implementing both these methods:
- (void) doSomethingWithObject:(ClassA*) object;
- (BOOL) doSomethingWithObject:(ClassA*) object;
3) A class declaring/implementing this method:
- (void) doSomethingWithObject:(ClassB*) object;
...when its superclass declares/implements this method:
- (void) doSomethingWithObject:(ClassA*) object;
(and the analogue for conflicting return value), both when A) ClassB descends from ClassA, and B) Not.

Question 1: no can do: Objective-C doesn't include the types in the method names; there is no mangling. It might work with Objective-C++ -- never used it that much.
Question 2: Same. Won't work.
Question 3: Will work.
EDIT: in general, method names do not include any types, so if you strip the types and they are the same then it will be considered the same, and therefore won't be allowed in the same class. Along the same lines, it WILL work if it's in different classes, although you might get some confusion if the types used in the call and the types used in what gets called don't quite agree.

You are thinking in terms of C++ where the compiler does the static binding of figuring out which instance method to call based on the type of the input.
Objective-C doesn't work that way. Instead, all binding is dynamic at run-time. Kinda like all methods being declared "virtual" in C++. The programmer is responsible for passing in appropriate variables that respond in the way your method expects.
Your method could query the object being passed in whether it responds to certain selectors and take appropriate action based on that if you wanted more robust behavior. Or your method could ask the object being passed in whether it is a type it expects. Again, this would all be done at run-time in your method. Not by the compiler.
So the answer is, declare as:
- (void) doSomethingWithObject:(id) object;
... then pass in whatever object you like.

Related

What is the (id) mean in the init method? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the meaning of id?
I am the newbie to Ios programming.
I saw the following declaration
- (id)init
what does (id) mean here?
id denotes a type which is compatible with any object. The notation
- (id)init
means the init instance method of your class; typically it's used to initialize the instantiated object after memory allocation (usually done using alloc). In Objective-C, methods' return type is declared by putting the type in parentheses before the method name. So, here it means that the init method may return any Objective-C object.
But you should really, really google an Objetive-C tutorial and read it. This is such a fundamental thing for which there is no excuse for not reading a tutorial or other documentation.
id is the plain C compatible type that represents an Objective-C object. This allows C source code to store, and interact with, Objective-C objects.
The reason for it to be of type 'id' is that the -init method is inherited all the way up from NSObject (in objective-C you can not overload methods, hence you can not change the argument/retrurn value types when subclassing). Since 'id' works with any object, this is OK.
EDIT It seems that specifying a concrete class as the return type of -init is OK, even though you are ultimately overriding '-[NSObject init]'.
I guess the use of 'id' is just a custom?
The fact that 'id' acts as a "generic Objective-C object pointer" that accepts any object type on assignment remains unchanged, though.
-(id)init is called to initialize the variables inside an object and do any necessary setup (it's basically the constructor).
A possiable duplication can be
What's the -(id)init method good for?

In Objective-C why is id used as return type for init methods?

I did some quick searching and couldn't find an answer for this.
I'm interested to know why in Objective-C, id is used as the return type for init methods.
My guess is that it's because if the class is overridden, you don't want to return an object of the superclass's type, but I'm interested to know if it's done for some other reason.
Yup. Your idea is right on the money. A subclass should still be able to use its superclass's initialization methods and return its own type instead of the super type and returning id allows it to do that.
The superclass type idea, while a good theory, doesn't really stand up: A NSString * is a NSObject *. There's no reason it can't be referred to as such.
Instead, I think it has more to do with function signatures. In a dynamic language like Objective-C, you can have no idea what class you're messaging. But the compiler must know what type is being returned. That and Objective-C's history of convention-based programming (rather than having strict rules) means that your subclass could return a NSRect (a struct) or NSInteger (a scalar) from init. It was kooky, but valid.
C++ has a similar problem, see Is the return type part of the function signature?.
So we needed a single type for all methods with a signature of -(id)init, and id was the only thing that made sense as it specified only that the return type was an instance. That's enough for the compiler to do the right thing. Now we have instancetype, which matches the class being messaged.
In the meantime Apple added a new way to declare the return type of init methods.
It is instancetype. Read more about it e.g. here
it's possible for init to actually return an instance of a different class, so id is used. can't say i've ever seen this happen in practice, but hey :)

Dynamic Getters and Setters with Objective C

I am in a situation where I want to dynamically generate getters and setters for a class at runtime (in a similar manner to what NSManagedObject does behind the scenes). From my understanding, this is possible using resolveInstanceMethod: on a specific class. At this point, you would have to use class_addMethod to dynamically add the method based on the selector. I understand this at a theoretical level, but I haven't delved much into the obj-c runtime, so I was curious if there were any great examples of how to do this. Most of my knowledge comes from this article:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html
Any thoughts / examples?
The only nice discussion I know is at Mike Ash's blog post. It's not that hard, actually.
I once needed to split a big NSManagedObject subclass into two, but decided to keep the fact an implementation detail so that I don't have to rewrite other parts of my app. So, I needed to synthesize getter and setter which sends [self foo] to [self.data foo], automatically.
To achieve that, I did the following:
Prepare the new method, already in my class.
- (id)_getter_
{
return objc_msgSend(self.data, _cmd);
}
- (void)_setter_:(id)value
{
objc_msgSend(self.data, _cmd,value);
}
Note that _cmd has the selector in it. So, usually, _cmd is either #selector(_getter_) or #selector(_setter_) in these methods, but I'm going to plug the implementation of _getter_ as the implementation of foo. Then, _cmd contains #selector(foo), and thus calls self.data's foo.
Write a generic synthesizing method:
+(void)synthesizeForwarder:(NSString*)getterName
{
NSString*setterName=[NSString stringWithFormat:#"set%#%#:",
[[getterName substringToIndex:1] uppercaseString],[getterName substringFromIndex:1]];
Method getter=class_getInstanceMethod(self, #selector(_getter_));
class_addMethod(self, NSSelectorFromString(getterName),
method_getImplementation(getter), method_getTypeEncoding(getter));
Method setter=class_getInstanceMethod(self, #selector(_setter_:));
class_addMethod(self, NSSelectorFromString(setterName),
method_getImplementation(setter), method_getTypeEncoding(setter));
}
Note that this is a class method. So self stands for the class. Note also that I didn't hardcode type encodings (which tells Objective-C runtime what the arguments of the particular method are). The syntax of type encodings is documented, but constructing by hand is very error-prone; I wasted a few days that way until Mike Ash told me to stop it. Generate it using an existing method.
Generate forwarders at the earliest possible time:
+(void)load
{
for(NSString*selectorName in [NSArray arrayWithObjects:#"foo", #"bar", #"baz",nil]){
[self synthesizeForwarder:selectorName];
}
}
This generates foo, setFoo:, bar, setBar:, and baz, setBaz:.
Hope this helps!
Another example is one I wrote, called DynamicStorage, available here:
https://github.com/davedelong/Demos
The primary impetus behind it was this question, which was asking how to use an NSMutableDictionary as the backing store for any object ivar. I wrote a class that will generate getters and setters for any #property, respecting things like a custom getter/setter name, the object memory management policy, etc. The neat thing about it is that it's using imp_implementationWithBlock() so that it only has to calculate the appropriate property name once (and then captures and saves it as part of the block).

Defining conditions in protocols

I have a protocol like this:
#protocol ProfileSubObjects <NSObject, NSCoding>
#required
- (BOOL) hasGraph;
#optional
- (NSArray *) xGraphValues;
- (NSArray *) yGraphValues;
I want to make required this two optional methods if hasGraph is equal to YES.
Is it possible?
No. Methods are either required by a protocol or they're not. For one thing, the value of -hasGraph isn't known at compile time. Since it's an instance method rather than a class method, it's not even known at run time until you create a particular object. Furthermore, the object might report different values for -hasGraph at different times.
The best thing to do here is to simply document the fact that if -hasGraph returns YES, the -xGraphValues and -yGraphValues are expected to be implemented. You could enforce that by throwing an exception, or you could fail gracefully and just not draw any data if those methods aren't implemented. Use the -respondsToSelector: method to check whether the method is implemented before you call it.
No, it's not possible. At least, not like this. However there is a deeper issue. The question suggests consideration of compile versus runtime checking and object orientation.
Marking something as #optional or #required means that you wish to perform compile time checking that those objects fulfil the protocol contract of providing implementations - or not in the case of #optional - of those methods.
Therefore there is no reason to have that compile time checking dependent upon the value of a runtime variable, in this case hasGraph.
A better approach would be to make use of the respondsToSelector message check. Alternatively you could have a subclass that has a graph and supplies x and y graph values.
That's not possible; the result of hasGraph will be known only at runtime, whereas the required/optional parts of a protocol are used for the compiler to check things out at compile time.
What you probably want to do is to add a strong note to the effect that if hasGraph returns YES then xGraphValues and yGraphValues must be implemented, bringing a little informality to your formal protocol. You can always do something like:
if([object respondsToSelector:#selector(xGraphValues)] &&
[object respondsToSelector:#selector(yGraphValues)])
To verify at runtime whether an object implements the parts of the protocol you need in order to be able to do a particular operation on it. It'd probably be smart to put that stuff in an NSAssert if you want someone who implements a non-conformant object to be able to find out what they did wrong through a debug build.

Implement a pure virtual method in Objective-C

I want to go to there. Seriously though, how does one implement a pure virtual method in an "Apple" way? Do you use a Protocol with your base class and throw exceptions on those methods?
When you program in Objective-C you need to purge your mind of such things as virtual methods. You don't call methods on Objective-C objects, you send messages to them. Objects either respond to messages or they don't, but due to the dynamic binding, you can't tell this until run time.
Thus, you can declare a method on a base object and not not provide an implementation, no problem (except for the compiler warning), but you can't have the compiler flag up when you directly instantiate an object with such methods and it won't throw an error at runtime unless you actually send that message to the object.
The best way to create "virtual" base classes (in my opinion) is to declare the method and give it a stub implementation that throws a suitable exception.
In Objective-C, there is no pure virtual support as in C++.
A simulation would be that you declare a method in your interface but don't implement it in your .m file. Of course you'd get compiler warnings but IIRC you can turn those off. But you won't get warnings/errors if you don't overwrite them in the subclass, which you get in C++ (IIRC).
An alternative would be to implement them with just an NSAssert(NO, #"Subclasses need to overwrite this method"); body. Still, you'd only catch this at runtime, not compiletime.
Depending on what you're doing the delegate pattern may be more appropriate than a subclass, where the delegate is defined as id<YourDelegateProtocol>. The compiler will generate a warning if the required methods in the delegate protocol are not implemented.
Subclassing is generally avoided in Objective-C since objects cannot inherit from multiple superclasses but they can implement multiple protocols.
You should use the:
- (void)doesNotRecognizeSelector:(SEL)aSelector method.
As noted by Apple, here: https://developer.apple.com/library/mac/#documentation/cocoa/reference/Foundation/Classes/NSObject_Class/Reference/Reference.html
You have a few options, but you're on the right track.
ObjC doesn't support this directly, forcing subclasses to implement a protocol is the best way to check it at compilation.
'Secretly' implementing the method in the base class and asserting is what I do to confirm the subclasser has subclassed correctly at runtime. Some people have mixed feelings about assertions, or must leave them active, so that's not always a good solution.
You can also force subclasses use a specific class constructor and initialization sequence, then verify they have implemented everything required before returning an instance, in case compiler warnings don't cut it.
But ObjC is missing some lang features which allow clients to shoot themselves in the foot, or workaround what they wish so... you shouldn't get too stuck on enforcing it.
note: Exceptions are very uncommon (and a bit unsafe, too) in ObjC.
A virtual method is a method whose behavior can be overridden within an inheriting class by a function with the same signature (i.e same name with same number of params and type of params).
Example:-
#implementation BaseClass
-(void)viewDidLoad
{
[self virtualMethod:123];
}
-(void)virtualMethod:(int)param
{
//implement this method in subclass
}
#end
////////////////////////////////////////////////////
#interface ChildClass:BaseClass
#end
#implementation ChildClass
-(void)virtualMethod:(int)param
{
NSLog(#"There is no keyword "Virtual" in Objective C.");
}
#end
Output:-
"There is no keyword "Virtual" in Objective C."