6

For example if there is a 'handle all' type method...

if ([obj isKindOfClass:class1]) {
    // ...
} else if ([obj isKindOfClass:class2]) {
    // etc..

Is this bad practice? Is there a neater alternative or a better way to structure the code?

Are there disadvantages in tearms of runtime, readability, maintainability or anything?

Tim
  • 5,024
  • 2
  • 30
  • 58
Robert
  • 37,670
  • 37
  • 171
  • 213

3 Answers3

7

Whenever something is considered good/bad practice, it is more or less subjective. When doing something is inherently right/wrong, it is more or less objective.

isKindOfClass: is a useful method to check class inheritance. It answers the only question, "is the object of a class which is (a subclass of) a given class?". It doesn't answer any other questions like "does this object implement that method in its own way?" or "can I use the object for X or Y?". If you use isKindOfClass: as intended, you won't have any problems. After all, in a dynamic typed language you ought to have tools to extract meta information about objects. isKindOfClass: is just one of the available tools.

The fact that certain objects may lie about their class should not really put you off. They just disguise themselves as objects of another class without breaking anything. And if that doesn't break anything, why should I care?

The main thing is that you should always remember to use the right tool for any given purpose. For example, isKindOfClass: is no substitute for respondsToSelector: or conformsToProtocol:.

Costique
  • 23,712
  • 4
  • 76
  • 79
1

Sort of. This question basically covers what you're asking: Is it safe to use isKindOfClass: against an NSString instance to determine type?

There are some caveats you need to bear in mind (see link above), but personally I think it's a fairly readable method. You just need to make sure what you're doing inside your conditional test is appropriate (the example Apple give is along the lines of "an object may say it's a kind of NSMutableArray, but you might not be able to mutate it").

Community
  • 1
  • 1
lxt
  • 31,146
  • 5
  • 78
  • 83
0

I would consider the example you gave to be an anti-pattern, so yes, I would say it is harmful. Using isKindOf like that is defeating polymorphism and object orientation.

I would far prefer that you call:

[obj doTheThing];

and then implement doTheThing differently in your subclasses.

If obj could belong to classes that you don't have control over, use categories to add your doTheThing method to them. If you need default behaviour, add a category on NSObject.

This is a cleaner solution in my opinion, and it helps to separate the logic (what you're doing) from the implementation details (how to do it for specific different types of object).

Sam Deane
  • 1,553
  • 1
  • 13
  • 17
  • Implementing methods in categories just to avoid the need of using introspection tools sounds worse to me. iE NSJSONSerialization's `JSONObjectWithData:options:error:` might return different types. (Array, dictionary). hacking dictionary method into arrays and vice-versa sound extremely stupid to me. – vikingosegundo Aug 07 '14 at 16:11
  • What if only a subclass needs to have a method? – Iulian Onofrei Nov 20 '14 at 14:31
  • If only a subclass needs to have a method, then have an method in the base class with a default implementation that does nothing, and an overridden method in the subclass that does something. – Sam Deane Nov 22 '14 at 17:03
  • With regard to the serialisation comment - yes, you can always find an example where isKindOfClass is appropriate, and that *might* be one. If you are in control of the classes yourself though, structuring the code to use polymorphism is almost always going to be better. A series of if/else statements checking the class of the receiver is really no better than using c structs with a 'type' field. – Sam Deane Nov 22 '14 at 17:05
  • In general you can use a base class or a protocol to define the interface that you're going to call - you'd only have to resort to categories in the rare cases where you want to be able to apply the behaviour to classes that you have no control over (eg system classes). – Sam Deane Nov 22 '14 at 17:08