Objective-C class extension

2019-01-22 06:36发布

问题:

As a fairly new objective-c programmer (with a 4 years Java experience), I seem to be having a hard time understanding when to use class extensions. From what I understood (and please, correct me if I'm wrong), the main difference between categories and extensions is that the extension expects you to implement the methods inside your main implementation, whereas with a category, it can be in another implementation. It also seems that people are using extensions mainly for private methods.

Here's my first question. What's the difference between using a class extension to declare a private method, and not declare it at all (it seems to compile in run in both cases)? (example 1 vs 2)

Example 1

@interface Class()
-(void) bar;
@end

@implementation Class
-(void) foo {
    [self bar];
}

-(void) bar {
    NSLog(@"bar");
}
@end

Example 2

@implementation Class
-(void) foo {
    [self bar];
}

-(void) bar {
    NSLog(@"bar");
}
@end

Second question: What's the difference between declaring ivars inside the extension and declaring it directly inside the implementation? (Exemple 3 vs 4)

Example 3

@interface Class() {
    NSArray *mySortedArray;
}
@end

@implementation Class
@end

Example 4

@implementation Class
NSArray *mySortedArray;
@end

I have a last question about coding conventions: when should I put an underscore (_) in front of a variable's name?

Thank you

回答1:

Methods in class extensions

It never used to be the case that you didn't need to declare your private methods. Until recently, you needed to declare your private methods somewhere, and most people chose a class extension to do so. From Xcode 4.4 (I believe), the compiler is clever enough to determine which methods are meant to be private within that implementation, removing the need to declare them elsewhere.

Variables in class extensions

As for examples 3 and 4, be careful. Within a class extension, the variable is an instance variable to that class (example 3). Example 4 declares a global variable (due to the fact it follows global variable semantics from C). Stick with example 3 for your private instance variables.

Coding conventions

As for the coding convention, it's up to the developer/team to decide whether to use an underscore or not. Our team uses m_ for private instance variables. Apple in their documentation suggest using underscores (that's the naming style for the underlying instance variables for synthesized properties). The important thing is, to be consistent throughout your code.



回答2:

the main difference between categories and extensions is that the extension expects you to implement the methods inside your main implementation, whereas with a category, it can be in another implementation. It also seems that people are using extensions mainly for private methods.

Correct.

What's the difference between using a class extension to declare a private method, and not declare it at all (it seems to compile in run in both cases)?

Maybe just a compiler warning regarding the undeclared selector. (Of course it runs fine - the method is implemented and does exist.) Also note that a declaration (a known, correct function signature) is necessary for the compiler in order to emit ABI-conformant, correct binary code. The assumption it makes about undeclared methods (namely that they return id and accept variadic arguments) may not be correct - calling a function through a pointer of an incompatible type is undefined behavior.

What's the difference between declaring ivars inside the extension and declaring it directly inside the implementation?

In the 4th example, it's a global C variable, it's not an instance variable of your class.

when should I put an underscore (_) in front of a variable's name?

Whenever you want, just do it consistently. Always or never.



回答3:

In question 1, example 2: The methods foo and bar implemented in Class are visible to instances of Class. If foo and bar aren't declared in a separate header file AND the implementation file isn't made available, another class will be unaware of the existence of foo and bar. foo and bar are private methods; instances of Class will still respond to foo and bar messages. Also, Xcode will flag a warning if another class that tries to message foo and bar since Xcode is unable to verify (without the declaration in the header file) that foo and bar exist. By contrast, example 1 declaration of bar allows any other class to send message bar to instances of Class. Xcode will also not flag an error for any message to bar if @interface Class is in a header file that is #import by the other class.

In question 2, example 4: mySortedArray is a local immutable array declared with local scope within Class. The mySortedArray in example 3 is an instance variable of type NSArray accessible to other class that creates an instance of Class.



回答4:

Hope subclass-category-and-extensions may be helpful for you.



回答5:

Excellent explanation on Class Extensions and Categores,

http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html