Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>This is a relatively common question for people transitioning from strongly type languages (like C++ or Java) to more weakly or dynamically typed languages like Python, Ruby, or Objective-C. In Objective-C, most objects inherit from <code>NSObject</code> (type <code>id</code>) (the rest inherit from an other root class such as <code>NSProxy</code> and can also be type <code>id</code>), and any message can be sent to any object. Of course, sending a message to an instance that it does not recognize may cause a runtime error (and will also cause a compiler <em>warning</em> with appropriate -W flags). As long as an instance responds to the message you send, you may not care what class it belongs to. This is often referred to as "duck typing" because "if it quacks like a duck [i.e. responds to a selector], it is a duck [i.e. it can handle the message; who cares what class it is]". </p> <p>You can test whether an instance responds to a selector at run time with the <code>-(BOOL)respondsToSelector:(SEL)selector</code> method. Assuming you want to call a method on every instance in an array but aren't sure that all instances can handle the message (so you can't just use <code>NSArray</code>'s <a href="http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/Classes/NSArray_Class/Reference/Reference.html#//apple_ref/doc/uid/20000137-BABCBHFG" rel="nofollow noreferrer"><code>-[NSArray makeObjectsPerformSelector:]</code></a>, something like this would work:</p> <pre><code>for(id o in myArray) { if([o respondsToSelector:@selector(myMethod)]) { [o myMethod]; } } </code></pre> <p>If you control the source code for the instances which implement the method(s) you wish to call, the more common approach would be to define a <code>@protocol</code> that contains those methods and declare that the classes in question implement that protocol in their declaration. In this usage, a <code>@protocol</code> is analogous to a Java Interface or a C++ abstract base class. You can then test for conformance to the entire protocol rather than response to each method. In the previous example, it wouldn't make much of a difference, but if you were calling multiple methods, it might simplify things. The example would then be:</p> <pre><code>for(id o in myArray) { if([o conformsToProtocol:@protocol(MyProtocol)]) { [o myMethod]; } } </code></pre> <p>assuming <code>MyProtocol</code> declares <code>myMethod</code>. This second approach is favored because it clarifies the intent of the code more than the first.</p> <p>Often, one of these approaches frees you from caring whether all objects in an array are of a given type. If you still do care, the standard dynamic language approach is to unit test, unit test, unit test. Because a regression in this requirement will produce a (likely unrecoverable) runtime (not compile time) error, you need to have test coverage to verify the behavior so that you don't release a crasher into the wild. In this case, peform an operation that modifies the array, then verify that all instances in the array belong to a given class. With proper test coverage, you don't even need the added runtime overhead of verifying instance identity. You do have good unit test coverage, don't you?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload