I am working with Objective-C in Xcode. I was wondering is there any mechanism to proof your code to make sure all functions and methods are declared in the .h file or in the private #interface method?
To clarify I will be on a coding tangent and will write a method directly in my viewController.m file
- (Awesome*) generateAwesomeOfMagnitude:(NSFloat)magnitude { ...
and I will forget to add the heading to the viewController.h file. If this is a private method nothing notifies me that I've done this so I have to go back through and verify that everything was declared manually when Im done. Is there any way to check automatically?
Note: Im looking to make the complier to throw a warning. Is there a setting is really what I should have asked.
Omar's answer is correct - asking an object if it will respond to a selector is the preferred method for probing objects to see if they'll respond to a method at runtime. However, the question asks "How to automatically verify all methods are declared?" (presumably at compile time). And the answer is, short of writing something yourself, you cannot automatically do this.
This is part of what makes Objective-C 'dynamic'. You don't have to declare a method anywhere. This makes things possible like:
id anUnknownObject = [[NSClassFromString(whoKnowsWhatIllBe) alloc] init];
[anUnknownObject performSelector:#selector(whoKnowsWhatIllDo)];
This means, for example, you could fetch a string from a web service and instantiate a class based on the string alone (of course the class must be around at run time in order to be instantiated, but the compiler doesn't have a clue).
This doesn't mean you should program this way, but it means its possible, and, as with most things, there are appropriate use cases, and it's a great distinction of the language. It promotes extreme decoupling, polymorphism, and tons-o'-fun patterns.
It's generally regarded as best practice to declare private methods in .m class extensions, but the value of this is for the programmer, not the compiler. Some (to include a major contributor to Objective-C who shall go nameless in public forums for the time being) have also suggested that there isn't a need to type the names of all your methods twice in a single file (less code, less mistakes -a bit more scrolling if you're looking at someone else's class for the first time). Having a nice-n-tidy public API is exactly what the header is for. Having a clean implementation is important, but the assumption is that once you're in the m, you're in private territory anyway. Scroll around. See what the method names are.
To check if method exists at run time in the class use
if([yourObject respondsToSelector:#selector(generateAwesomeOfMagnitude:)])
//has this method
else
//does not have this method
but you dont get any warning if you define a method in the .m and dont include it in the .h file
However if another class is accessing a method that is not declared in the .h file you will receive a warning
Related
I've been reading a little bit about this and what I don't understand is why people adds class extensions to make a method private.
Wouldn't it suffice to just leave it out from the header file?
It looks to me to be enough, but I might be missing a bigger point?
Short answer: now (as of Xcode 4.4, I think), you don't. Reason: you don't need to forward declare methods. Put your private methods in your .m file, and you're done.
Previously (Xcode 4.3 and older), you had to forward declare your methods before you could call them. Because you already declared the class in the .h file, you can't declare it again in the .m file, so a class extension is the way to add methods to an already declared class.
Edit: as #Yar mentioned above (and below), a private method in a .m file that isn't declared would not be visible to subclasses of that class, meaning it would be impossible for that subclass to call or override that method. Still, I'd be inclined to just not bother declaring it, unless/until you end up with a subclass that needs to override or call it. For me this happens pretty infrequently.
It would be sufficient to leave it out of the header file, but then your subclasses don't know it's there, either. This means that you get a compiler error if you try to call these private methods. This is why you use an external file that is a class extension, and all subclasses import that extension in the .m file.
Obviously, this situation is not ideal because you get three files for each class, minimum, but the joy of Objective-C is about making LOTS of files and not worry about it. If you are scared to make files, you will end up with big classes, which is an anti-pattern.
One problem is naming the class extension file, since it's a category with no, um, category. I've been using a scheme like Blah4Subclasses, which is probably about as bad a suggestion as you'll get.
the class continuation has nothing to do with access, wrt the translation. the objc language does not specify access for methods. so it's a relatively weak private. what people end up falling back on is the ability to hide method declarations in their implementation file.
the important point to take away is that the class continuation is generally only visible to your class (because it is often placed in the *.m file). this pattern reduces the likelihood of a private method's use because it is not visible to the client, or to the compiler (in translations other than the one which contains the class' #implementation in the typical structure).
also note that the class continuation is capable of a lot -- so it's a convenient place to store your private #interface; properties, ivars, methods.
lastly, it is also a habit from earlier days, because it was a more frequent necessity. not too long ago, the declaration was added so the compiler knew the object responded to a specific selector, and the signature of that selector. because clang parses the entire #implementation block these days, many people find they do not need the declarations in the class continuation because the compiler can match methods seen in the #implementation, regardless of order of declaration.
You can add #private in your .h file.
Assume that:
New Protocol is declared
Method in this protocol is marked #required
Class conforms to Protocol
Class does not implement the method mentioned in Protocol
At compile time, information about this method is known: i.e. that it is required and that this class and any other classes this class may may extend do not implement it.
Why in this case the compiler issues a warning and not an error?
Errors are only issued when the compiler cannot continue because something went terribly wrong.
When calling a method in Objective-C, the method lookup is done during runtime and not during compilation, which C++ does. In Objective-C a "message" is simply sent to the object, something like obj.executeCommand("Hey, can you execute function <name> for me?"). In C++ the object will be called directly, in a way like obj.<name>(). In the case of Objective-C the executeCommand() method is called, which exists. In C++'s case the function is called but it does not exist. These are methods that are linked on the compiler level, which means they both become memory addresses rather than names. executeCommand becomes 0x12345678 but it still uses the same message ("execute function <name>").
This is probably very confusing, but it's related to the way methods are implemented in different languages.
If you feel strongly about it, why not turn on -Werror?
I don't know the real answer but here is a use case that would go against it.
What if you implemented all of the protocol methods in a category???
Main interface declaration adopts the protocol however the protocol method implementation is in a category.
This is valid code but will show compile error if compiler was that strict !!
Objective-C is a dynamic language. The idea of what an implementation is, is different to a static language.
For the most part, it's in code that most of us implement inside the #implementation ... #end block.
But what if a method is not found? Then an object has a chance deal with it dynamically.
Imagine you have an interface for a sound effect player:
#protocol FX
- (void)playBeep;
- (void)playSiren;
- (void)playHonk;
#end
An implementation could have the files Beep.mp3, Siren.mp3, Honk.mp3 to play, but instead of implementing each of the methods, it could override -forwardInvocation: and parse the selector string, something like this pseudocode:
NSString *selName = NSStringFromSelector([invocation selector]);
if ([selName startsWith:#"play"]) {
NSString filename = fileNameFromSelector(selName);
[self playSoundFileNamed:filename];
}
This may seem contrived, but once you start using the dynamic features of the language, you will start finding more and more places where it makes sense. And by sense I mean, does this effort help in the long run?
In the above case, just add a -sound* method name to the interface, and drop in a appropriately named sound file. It just works.
Another example from personal experiments: how to deal with Core Data entities in a more natural way. I want to do this:
NSArray *people = [Person findAllWithNameLike:#"B%"];
instead of mucking about with predicates, fetch requests etc.
But I don't want to define every permutation of method in code.
How about if I wanted to build an XML builder? I would look at a dynamic approach. It has served Groovy Builders well (look at Groovy/Grails for examples).
One last example: I have a traits system where I can define behaviours in the form of groups of methods and have my objects assimilate this behaviour. So, while the compiler doesn't see an implementation for the interface my object conforms to, the implementation is injected into it from a trait class, using the Objective-C runtime. Why would I do this? I find many delegate methods are boiler plate, but at the same time, a single base class for each situation is not flexible enough. Instead of cut and paste from code samples, my 'samples' compile and run :) and any changes are reflected across all projects using the trait.
To really understand why all this is available to you, it is worth playing around with a Smalltalk environment (search Pharo or Squeak). This is where Objective-C has its roots.
And finally, to stop these warnings:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wprotocol"
#implementation ... #end
#pragma clang diagnostic pop
Because there are times when there are bogus "required" methods in a poorly designed protocol.
They should have been optional but someone insisted they are "required".
Thusly making this a run time issue rather than a compile bug is very very wise.
If you write method implementations in Objective-C, it is pretty standard to sum up the methods of a class in the corresponding #interface blocks. Publically accessible methods go in the header file's interface, not-so-public methods can go in an empty category on top of the implementation file.
But it's not neccessary to declare an interface for every method. If you only reference the methods below their implementation code of the same class/file, there's no need to put any declaration anywhere else.
-(void) doSomething {
}
-(void) doSomethingElse {
[self doSomething];
}
Coming from another language, this is new to me. And I can't seem to decide whether it is nice and pretty to keep the interface blocks clean, or whether it should be prevented because the order of method implementations seem like a weird dependency to have.
What is the general public's opinion of this matter?
The general rule I follow is that if the only method calling doSomething is doSomethingElse then it's fine to not have doSomething be part of the declared private interface. But the moment a second method makes use of doSomething I add it to the declared interface.
The thinking behind this is that as long as the method is only ever called from one place there's no reason to think of it as modular or reusable code. Instead it's more like the method exists just to tidy up the implementation of its calling method. In essence, the method doesn't really stand on its own, so there's no point in treating it like an interface method. But as soon as a second method is making the same call it demonstrates that the code is in fact reusable and useful in more than just the original context, and able to stand on its own as a useful function. So at that point, it becomes a declared part of the private interface.
Some other coding style choices make answering this question really easy:
If you document every method at its declaration point, then not having a declaration means that either these methods are missing documentation, or they are documented at definition; either way it's inconsistent. If you follow the school of thought that most methods should be so self-explanatory from their name that they don't need documentation, this might not be an issue.
Some people advocate ordering methods from more general to more specific; in that model your example is ordered wrong, and the only way to fix it is to have a declaration.
There's also the question of whether you would find it annoying to get unexpected compiler errors when you do simple re-ordering or re-factoring just because you happened to start using a method earlier, and have to stop and add the declaration at that point.
How come sometimes you need to put the method signature in the .h file and sometimes you don't?
Methods which you are overriding from your superclass do not need to be redeclared in your class's interface. It is sometimes a good idea to do so, but is not required.
Similarly, you do not need to declare methods that you are implementing from a protocol; simply declaring that you conform to the protocol is enough.
You should declare methods which are "new" to your class: those which are not inherited from a superclass nor part of a protocol. This is to give the compiler the necessary information to determine the correct argument and return types and is necessary to the correct running of your application.
Those answerers who have said that you don't have to declare your methods are technical correct, however be aware that this is a very bad practice as the compiler will infer parameter and return types which may not match the definition and can cause undefined behavior when the method is called.
This is just because some people like to put it in the header. Some people don't. You might have notice that in the .h files there is an #interface. You technically just need to put method signatures there. But, trust me, it makes life a lot easier if its in the header file (mostly because its more readable).
Because technically objects have no methods in Objective-C as we know them from other languages, instead what you are doing is to send messages to the object, if there is a corresponding method (message) on the object with the same signature, it will be called. This means there is no real need to have the signatures in the header however it is good practice to have them so that the compiler can warn if you write the wrong signature.
It's always a good idea to declare methods in the #interface before using them (it helps the compiler, allowing the compiler to help you by catching more type errors), but the header file should really only have public methods (methods you want other classes to know about). For private methods that are used internally by the class, a class extension within the .m file is a good idea, i.e.:
#interface MyClass ()
-(void) superSecretMethod;
#end
It's always a good idea to put the signature of your public methods in the .h file. You will avoid compiler warnings, and you'll know that if you do get a warning, it's for a good reason (you mistyped your method name, parameter type, etc).
I've seen a number of strategies for declaring semi-private methods in Objective-C, but there does not seem to be a way to make a truly private method. I accept that. But, why is this so? Every explanation I've essentially says, "you can't do it, but here's a close approximation."
There are a number of keywords applied to ivars (members) that control their scope, e.g. #private, #public, #protected. Why can't this be done for methods as well? It seems like something the runtime should be able to support. Is there an underlying philosophy I'm missing? Is this deliberate?
The answer is... well... simple. Simplicity and consistency, in fact.
Objective-C is purely dynamic at the moment of method dispatch. In particular, every method dispatch goes through the exact same dynamic method resolution point as every other method dispatch. At runtime, every method implementation has the exact same exposure and all of the APIs provided by the Objective-C runtime that work with methods and selectors work equally the same across all methods.
As many have answered (both here and in other questions), compile-time private methods are supported; if a class doesn't declare a method in its publicly available interface, then that method might as well not exist as far as your code is concerned. In other words, you can achieve all of the various combinations of visibility desired at compilation time by organizing your project appropriately.
There is little benefit to duplicating the same functionality into the runtime. It would add a tremendous amount of complexity and overhead. And even with all of that complexity, it still wouldn't prevent all but the most casual developer from executing your supposedly "private" methods.
EDIT: One of the assumptions I've
noticed is that private messages would
have to go through the runtime
resulting in a potentially large
overhead. Is this absolutely true?
Yes, it is. There's no reason to suppose that the implementor of a class would not want to use all of the Objective-C feature set in the implementation, and that means that dynamic dispatch must happen. However, there is no particular reason why private methods couldn't be dispatched by a special variant of objc_msgSend(), since the compiler would know that they were private; i.e. this could be achieved by adding a private-only method table to the Class structure.
There would be no way for a private
method to short-circuit this check or
skip the runtime?
It couldn't skip the runtime, but the runtime wouldn't necessarily have to do any checking for private methods.
That said, there's no reason that a third-party couldn't deliberately call objc_msgSendPrivate() on an object, outside of the implementation of that object, and some things (KVO, for example) would have to do that. In effect, it would just be a convention and little better in practice than prefixing private methods’ selectors or not mentioning them in the interface header.
To do so, though, would undermine the pure dynamic nature of the language. No longer would every method dispatch go through an identical dispatch mechanism. Instead, you would be left in a situation where most methods behave one way and a small handful are just different.
This extends beyond the runtime as there are many mechanisms in Cocoa built on top of the consistent dynamism of Objective-C. For example, both Key Value Coding and Key Value Observation would either have to be very heavily modified to support private methods — most likely by creating an exploitable loophole — or private methods would be incompatible.
The runtime could support it but the cost would be enormous. Every selector that is sent would need to be checked for whether it is private or public for that class, or each class would need to manage two separate dispatch tables. This isn't the same for instance variables because this level of protection is done at compile time.
Also, the runtime would need to verify that the sender of a private message is of the same class as the receiver. You could also bypass private methods; if the class used instanceMethodForSelector:, it could give the returned IMP to any other class for them to invoke the private method directly.
Private methods could not bypass the message dispatch. Consider the following scenario:
A class AllPublic has a public instance method doSomething
Another class HasPrivate has a private instance method also called doSomething
You create an array containing any number of instances of both AllPublic and HasPrivate
You have the following loop:
for (id anObject in myArray)
[anObject doSomething];
If you ran that loop from within AllPublic, the runtime would have to stop you sending doSomething on the HasPrivate instances, however this loop would be usable if it was inside the HasPrivate class.
The answers posted thus far do a good job of answering the question from a philosophical perspective, so I'm going to posit a more pragmatic reason: what would be gained by changing the semantics of the language? It's simple enough to effectively "hide" private methods. By way of example, imagine you have a class declared in a header file, like so:
#interface MyObject : NSObject {}
- (void) doSomething;
#end
If you have a need for "private" methods, you can also put this in the implementation file:
#interface MyObject (Private)
- (void) doSomeHelperThing;
#end
#implementation MyObject
- (void) doSomething
{
// Do some stuff
[self doSomeHelperThing];
// Do some other stuff;
}
- (void) doSomeHelperThing
{
// Do some helper stuff
}
#end
Sure, it's not quite the same as C++/Java private methods, but it's effectively close enough, so why alter the semantics of the language, as well as the compiler, runtime, etc., to add a feature that's already emulated in an acceptable way? As noted in other answers, the message-passing semantics -- and their reliance on runtime reflection -- would make handling "private" messages non-trivial.
The easiest solution is just to declare some static C functions in your Objective-C classes. These only have file scope as per the C rules for the static keyword and because of that they can only be used by methods in that class.
No fuss at all.
Yes, it can be done without affecting the runtime by utilizing a technique already employed by the compiler(s) for handling C++: name-mangling.
It hasn't been done because it hasn't been established that it would solve some considerable difficulty in the coding problem space that other techniques (e.g., prefixing or underscoring) are able to circumvent sufficiently. IOW, you need more pain to overcome ingrained habits.
You could contribute patches to clang or gcc that add private methods to the syntax and generated mangled names that it alone recognized during compilation (and promptly forgot). Then others in the Objective-C community would be able to determine whether it was actually worthwhile or not. It's likely to be faster that way than trying to convince the developers.
Essentially, it has to do with Objective-C's message-passing form of method calls. Any message can be sent to any object, and the object chooses how to respond to the message. Normally it will respond by executing the method named after the message, but it could respond in a number of other ways too. This doesn't make private methods completely impossible — Ruby does it with a similar message-passing system — but it does make them somewhat awkward.
Even Ruby's implementation of private methods is a bit confusing to people because of the strangeness (you can send the object any message you like, except for the ones on this list!). Essentially, Ruby makes it work by forbidding private methods to be called with an explicit receiver. In Objective-C it would require even more work since Objective-C doesn't have that option.
It's an issue with the runtime environment of Objective-C. While C/C++ compiles down into unreadable machine code, Objective-C still maintains some human-readable attributes like method names as strings. This gives Objective-C the ability to perform reflective features.
EDIT: Being a reflective language without strict private methods makes Objective-C more "pythonic" in that you trust other people that use your code rather than restrict what methods they can call. Using naming conventions like double underscores is meant to hide your code from a casual client coder, but won't stop coders needing to do more serious work.
There are two answers depending on the interpretation of the question.
The first is by hiding the method implementation from the interface. This is used, typically with a category with no name (e.g. #interface Foo()). This permits the object to send those messages but not others - though one might still override accidentally (or otherwise).
The second answer, on the assumption that this is about performance and inlining, is made possible but as a local C function instead. If you wanted a ‘private foo(NSString *arg)‘ method, you would do void MyClass_foo(MyClass *self, NSString *arg) and call it as a C function like MyClass_foo(self,arg). The syntax is different, but it acts with the sane kind of performance characteristics of C++'s private methods.
Although this answers the question, I should point out that the no-name category is by far the more common Objective-C way of doing this.
Objective-C doesn't support private methods because it doesn't need them.
In C++, every method must be visible in the declaration of the class. You can't have methods that someone including the header file cannot see. So if you want methods that code outside your implementation shouldn't use, you have no choice, the compiler must give you some tool so you can tell it that the method must not be used, that is the "private" keyword.
In Objective-C, you can have methods that are not in the header file. So you achieve the same purpose very easily by not adding the method to the header file. There's no need for private methods. Objective-C also has the advantage that you don't need to recompile every user of a class because you changed private methods.
For instance variables, that you used to have to declare in the header file (not anymore), #private, #public and #protected are available.
A missing answer here is: because private methods are a bad idea from an evolvability point of view. It might seem a good idea to make a method private when writing it, but it is a form of early binding. The context might change, and a later user might want to use a different implementation. A bit provocative: "Agile developers don't use private methods"
In a way, just like Smalltalk, Objective-C is for grown-up programmers. We value knowing what the original developer assumed the interface should be, and take the responsibility to deal with the consequences if we need to change implementation. So yes, it is philosophy, not implementation.