From e3b20c7e26cdbe77932a344a19402c4431a35f92 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Wed, 8 Jan 2014 21:27:42 -0600 Subject: Add categories description and Car example. --- objective-c.html.markdown | 95 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 5 deletions(-) diff --git a/objective-c.html.markdown b/objective-c.html.markdown index 453a42a5..b6b378d5 100644 --- a/objective-c.html.markdown +++ b/objective-c.html.markdown @@ -444,11 +444,96 @@ distance = 18; // References "long distance" from MyClass implementation @end // States the end of the implementation -/* - * A protocol declares methods that can be implemented by any class. - * Protocols are not classes themselves. They simply define an interface - * that other objects are responsible for implementing. - */ +// Categories +// A category is a group of methods designed to extend a class. They allow you to add new methods +// to an existing class for organizational purposes. This is not to be mistaken with subclasses. +// Subclasses are meant to CHANGE functionality of an object while categories instead ADD +// functionality to an object. +// Categories allow you to: +// -- Add methods to an existing class for organizational purposes. +// -- Allow you to extend Objective-C object classes (ex: NSString) to add your own methods. +// -- Add ability to create protected and private methods to classes. +// NOTE: Do not override methods of the base class in a category even though you have the ability +// to. Overriding methods may cause compiler errors later between different categories and it +// ruins the purpose of categories to only ADD functionality. Subclass instead to override methods. + +// Here is a simple Car base class. +@interface Car : NSObject + +@property NSString *make; +@property NSString *color; + +- (void)turnOn; +- (void)accelerate; + +@end + +// And the simple Car base class implementation: +#import "Car.h" + +@implementation Car + +@synthesize make = _make; +@synthesize color = _color; + +- (void)turnOn { + NSLog(@"Car is on."); +} +- (void)accelerate { + NSLog(@"Accelerating."); +} + +@end + +// Now, if we wanted to create a Truck object, we would create a subclass of Car instead as it would +// be changing the functionality of the Car to behave like a truck. But lets say we want to just add +// functionality to this existing Car. A good example would be to clean the car. So we would create +// a category to add these cleaning methods: +// @interface filename: Car+Clean.h +#import "Car.h" // Make sure to import base class to extend. + +@interface Car (Clean) // The category name is inside () following the name of the base class. + +- (void)washWindows; // Names of the new methods we are adding to our Car object. +- (void)wax; + +@end + +// @implementation filename: Car+Clean.m +#import "Car+Clean.h" + +@implementation Car (Clean) + +- (void)washWindows { + NSLog(@"Windows washed."); +} +- (void)wax { + NSLog(@"Waxed."); +} + +@end + +// Any Car object instance has the ability to use a category. All they need to do is import it: +#import "Car+Clean.h" // Import as many different categories as you want to use. +#import "Car.h" // Also need to import base class to use it's original functionality. + +int main(int argc, const char *argv[]) { + @autoreleasepool { + Car *mustang = [[Car alloc] init]; + mustang.color = @"Red"; + mustang.make = @"Ford"; + + [mustang turnOn]; // Use methods from base Car class. + [mustang washWindows]; // Use methods from Car's Clean category. + } + return 0; +} + + +// Protocols +// A protocol declares methods that can be implemented by any class. +// Protocols are not classes themselves. They simply define an interface +// that other objects are responsible for implementing. @protocol MyProtocol - (void)myProtocolMethod; @end -- cgit v1.2.3 From e3853e564bea5a1463ee7b1ec4b9beaaae295d0c Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Wed, 8 Jan 2014 21:55:20 -0600 Subject: Add description and example of how to simulate protected methods. --- objective-c.html.markdown | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/objective-c.html.markdown b/objective-c.html.markdown index b6b378d5..33200b63 100644 --- a/objective-c.html.markdown +++ b/objective-c.html.markdown @@ -430,7 +430,12 @@ distance = 18; // References "long distance" from MyClass implementation return @42; } +<<<<<<< HEAD // To create a private method, create the method in the @implementation but not in the @interface +======= +// Objective-C does not have private method declarations, but you can simulate them. +// To simulate a private method, create the method in the @implementation but not in the @interface. +>>>>>>> 421f48c... Add description and example of how to simulate protected methods. - (NSNumber *)secretPrivateMethod { return @72; } @@ -485,11 +490,11 @@ distance = 18; // References "long distance" from MyClass implementation @end -// Now, if we wanted to create a Truck object, we would create a subclass of Car instead as it would +// Now, if we wanted to create a Truck object, we would instead create a subclass of Car as it would // be changing the functionality of the Car to behave like a truck. But lets say we want to just add // functionality to this existing Car. A good example would be to clean the car. So we would create // a category to add these cleaning methods: -// @interface filename: Car+Clean.h +// @interface filename: Car+Clean.h (BaseClassName+CategoryName.h) #import "Car.h" // Make sure to import base class to extend. @interface Car (Clean) // The category name is inside () following the name of the base class. @@ -499,8 +504,8 @@ distance = 18; // References "long distance" from MyClass implementation @end -// @implementation filename: Car+Clean.m -#import "Car+Clean.h" +// @implementation filename: Car+Clean.m (BaseClassName+CategoryName.m) +#import "Car+Clean.h" // Import the Clean category's @interface file. @implementation Car (Clean) @@ -511,13 +516,13 @@ distance = 18; // References "long distance" from MyClass implementation NSLog(@"Waxed."); } -@end +@end // Any Car object instance has the ability to use a category. All they need to do is import it: #import "Car+Clean.h" // Import as many different categories as you want to use. #import "Car.h" // Also need to import base class to use it's original functionality. -int main(int argc, const char *argv[]) { +int main (int argc, const char * argv[]) { @autoreleasepool { Car *mustang = [[Car alloc] init]; mustang.color = @"Red"; @@ -529,6 +534,24 @@ int main(int argc, const char *argv[]) { return 0; } +// Objective-C does not have protected method declarations but you can simulate them. +// Create a category containing all of the protected methods, then import it ONLY into the +// @implementation file of a class belonging to the Car class: +@interface Car (Protected) // Naming category 'Protected' to remember methods are protected. + +- (void)lockCar; // Methods listed here may only be created by Car objects. + +@end +//To use protected methods, import the category, then implement the methods: +#import "Car+Protected.h" // Remember, import in the @implementation file only. + +@implementation Car + +- (void)lockCar { + NSLog(@"Car locked."); // Instances of Car can't use lockCar because it's not in the @interface. +} + +@end // Protocols // A protocol declares methods that can be implemented by any class. -- cgit v1.2.3 From 4b44b03a07bf6ffc1f265fa0f08e8ef8ceeae8d3 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Wed, 8 Jan 2014 23:37:43 -0600 Subject: Add extensions description with example. --- objective-c.html.markdown | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/objective-c.html.markdown b/objective-c.html.markdown index 33200b63..47af5ae8 100644 --- a/objective-c.html.markdown +++ b/objective-c.html.markdown @@ -553,6 +553,42 @@ int main (int argc, const char * argv[]) { @end +// Extensions +// Extensions allow you to override public access property attributes and methods of an @interface. +// @interface filename: Shape.h +@interface Shape : NSObject // Base Shape class extension overrides below. + +@property (readonly) NSNumber *numOfSides; + +- (int)getNumOfSides; + +@end +// You can override numOfSides variable or getNumOfSides method to edit them with an extension: +// @implementation filename: Shape.m +#import "Shape.h" +// Extensions live in the same file as the class @implementation. +@interface Shape () // () after base class name declares an extension. + +@property (copy) NSNumber *numOfSides; // Make numOfSides copy instead of readonly. +-(NSNumber)getNumOfSides; // Make getNumOfSides return a NSNumber instead of an int. +-(void)privateMethod; // You can also create new private methods inside of extensions. + +@end +// The main @implementation: +@implementation Shape + +@synthesize numOfSides = _numOfSides; + +-(NSNumber)getNumOfSides { // All statements inside of extension must be in the @implementation. + return _numOfSides; +} +-(void)privateMethod { + NSLog(@"Private method created by extension. Shape instances cannot call me."); +} + +@end + + // Protocols // A protocol declares methods that can be implemented by any class. // Protocols are not classes themselves. They simply define an interface -- cgit v1.2.3 From 718c2289e54fb707e49ca373b8083d7e85bf8dde Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Thu, 9 Jan 2014 19:56:23 -0600 Subject: Add much more to the protocols section. --- objective-c.html.markdown | 70 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 3 deletions(-) diff --git a/objective-c.html.markdown b/objective-c.html.markdown index 47af5ae8..9e41e135 100644 --- a/objective-c.html.markdown +++ b/objective-c.html.markdown @@ -449,7 +449,9 @@ distance = 18; // References "long distance" from MyClass implementation @end // States the end of the implementation +/////////////////////////////////////// // Categories +/////////////////////////////////////// // A category is a group of methods designed to extend a class. They allow you to add new methods // to an existing class for organizational purposes. This is not to be mistaken with subclasses. // Subclasses are meant to CHANGE functionality of an object while categories instead ADD @@ -553,7 +555,9 @@ int main (int argc, const char * argv[]) { @end +/////////////////////////////////////// // Extensions +/////////////////////////////////////// // Extensions allow you to override public access property attributes and methods of an @interface. // @interface filename: Shape.h @interface Shape : NSObject // Base Shape class extension overrides below. @@ -588,15 +592,75 @@ int main (int argc, const char * argv[]) { @end - +/////////////////////////////////////// // Protocols +/////////////////////////////////////// // A protocol declares methods that can be implemented by any class. // Protocols are not classes themselves. They simply define an interface // that other objects are responsible for implementing. -@protocol MyProtocol - - (void)myProtocolMethod; + // @protocol filename: "CarUtilities.h" +@protocol CarUtilities // => Name of another protocol this protocol includes. + @property BOOL engineOn; // Adopting class must @synthesize all defined @properties and + - (void)turnOnEngine; // all defined methods. +@end +// Below is an example class implementing the protocol. +#import "CarUtilities.h" // Import the @protocol file. + +@interface Car : NSObject // Name of protocol goes inside <> + // You don't need the @property or method names here for CarUtilities. Only @implementation does. +- (void)turnOnEngineWithUtilities:(id )car; // You can use protocols as data too. +@end +// The @implementation needs to implement the @properties and methods for the protocol. +@implementation Car : NSObject + +@synthesize engineOn = _engineOn; // Create a @synthesize statement for the engineOn @property. + +- (void)turnOnEngine { // Implement turnOnEngine however you would like. Protocols do not define + _engineOn = YES; // how you implement a method, it just requires that you do implement it. +} +// You may use a protocol as data as you know what methods and variables it has implemented. +- (void)turnOnEngineWithCarUtilities:(id )objectOfSomeKind { + [objectOfSomeKind engineOn]; // You have access to object variables + [objectOfSomeKind turnOnEngine]; // and the methods inside. + [objectOfSomeKind engineOn]; // May or may not be YES. Class implements it however it wants. +} + @end +// Instances of Car now have access to the protocol. +Car *carInstance = [[Car alloc] init]; +[[carInstance setEngineOn:NO]; +[carInstance turnOnEngine]; +if ([carInstance engineOn]) { + NSLog(@"Car engine is on."); // prints => "Car engine is on." +} +// Make sure to check if an object of type 'id' implements a protocol before calling protocol methods: +if ([myClass conformsToProtocol:@protocol(CarUtilities)]) { + NSLog(@"This does not run as the MyClass class does not implement the CarUtilities protocol."); +} else if ([carInstance conformsToProtocol:@protocol(CarUtilities)]) { + NSLog(@"This does run as the Car class implements the CarUtilities protocol."); +} +// Categories may implement protocols as well: @interface Car (CarCategory) +// You may implement many protocols: @interface Car : NSObject +// NOTE: If two or more protocols rely on each other, make sure to forward-declare them: +#import "Brother.h" + +@protocol Brother; // Forward-declare statement. Without it, compiler would through error. + +@protocol Sister + +- (void)beNiceToBrother:(id )brother; +@end +// See the problem is that Sister relies on Brother, and Brother relies on Sister. +#import "Sister.h" + +@protocol Sister; // These lines stop the recursion, resolving the issue. + +@protocol Brother + +- (void)beNiceToSister:(id )sister; + +@end /////////////////////////////////////// // Memory Management -- cgit v1.2.3 From 57c16ffb5ca3c91d163479f3d0d6eaddf51fb123 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Thu, 9 Jan 2014 19:56:23 -0600 Subject: Add much more to the protocols section. --- objective-c.html.markdown | 74 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 7 deletions(-) diff --git a/objective-c.html.markdown b/objective-c.html.markdown index 47af5ae8..781cdd3e 100644 --- a/objective-c.html.markdown +++ b/objective-c.html.markdown @@ -430,12 +430,8 @@ distance = 18; // References "long distance" from MyClass implementation return @42; } -<<<<<<< HEAD -// To create a private method, create the method in the @implementation but not in the @interface -======= // Objective-C does not have private method declarations, but you can simulate them. // To simulate a private method, create the method in the @implementation but not in the @interface. ->>>>>>> 421f48c... Add description and example of how to simulate protected methods. - (NSNumber *)secretPrivateMethod { return @72; } @@ -449,7 +445,9 @@ distance = 18; // References "long distance" from MyClass implementation @end // States the end of the implementation +/////////////////////////////////////// // Categories +/////////////////////////////////////// // A category is a group of methods designed to extend a class. They allow you to add new methods // to an existing class for organizational purposes. This is not to be mistaken with subclasses. // Subclasses are meant to CHANGE functionality of an object while categories instead ADD @@ -553,7 +551,9 @@ int main (int argc, const char * argv[]) { @end +/////////////////////////////////////// // Extensions +/////////////////////////////////////// // Extensions allow you to override public access property attributes and methods of an @interface. // @interface filename: Shape.h @interface Shape : NSObject // Base Shape class extension overrides below. @@ -588,15 +588,75 @@ int main (int argc, const char * argv[]) { @end - +/////////////////////////////////////// // Protocols +/////////////////////////////////////// // A protocol declares methods that can be implemented by any class. // Protocols are not classes themselves. They simply define an interface // that other objects are responsible for implementing. -@protocol MyProtocol - - (void)myProtocolMethod; + // @protocol filename: "CarUtilities.h" +@protocol CarUtilities // => Name of another protocol this protocol includes. + @property BOOL engineOn; // Adopting class must @synthesize all defined @properties and + - (void)turnOnEngine; // all defined methods. +@end +// Below is an example class implementing the protocol. +#import "CarUtilities.h" // Import the @protocol file. + +@interface Car : NSObject // Name of protocol goes inside <> + // You don't need the @property or method names here for CarUtilities. Only @implementation does. +- (void)turnOnEngineWithUtilities:(id )car; // You can use protocols as data too. +@end +// The @implementation needs to implement the @properties and methods for the protocol. +@implementation Car : NSObject + +@synthesize engineOn = _engineOn; // Create a @synthesize statement for the engineOn @property. + +- (void)turnOnEngine { // Implement turnOnEngine however you would like. Protocols do not define + _engineOn = YES; // how you implement a method, it just requires that you do implement it. +} +// You may use a protocol as data as you know what methods and variables it has implemented. +- (void)turnOnEngineWithCarUtilities:(id )objectOfSomeKind { + [objectOfSomeKind engineOn]; // You have access to object variables + [objectOfSomeKind turnOnEngine]; // and the methods inside. + [objectOfSomeKind engineOn]; // May or may not be YES. Class implements it however it wants. +} + @end +// Instances of Car now have access to the protocol. +Car *carInstance = [[Car alloc] init]; +[[carInstance setEngineOn:NO]; +[carInstance turnOnEngine]; +if ([carInstance engineOn]) { + NSLog(@"Car engine is on."); // prints => "Car engine is on." +} +// Make sure to check if an object of type 'id' implements a protocol before calling protocol methods: +if ([myClass conformsToProtocol:@protocol(CarUtilities)]) { + NSLog(@"This does not run as the MyClass class does not implement the CarUtilities protocol."); +} else if ([carInstance conformsToProtocol:@protocol(CarUtilities)]) { + NSLog(@"This does run as the Car class implements the CarUtilities protocol."); +} +// Categories may implement protocols as well: @interface Car (CarCategory) +// You may implement many protocols: @interface Car : NSObject +// NOTE: If two or more protocols rely on each other, make sure to forward-declare them: +#import "Brother.h" + +@protocol Brother; // Forward-declare statement. Without it, compiler would through error. + +@protocol Sister + +- (void)beNiceToBrother:(id )brother; +@end +// See the problem is that Sister relies on Brother, and Brother relies on Sister. +#import "Sister.h" + +@protocol Sister; // These lines stop the recursion, resolving the issue. + +@protocol Brother + +- (void)beNiceToSister:(id )sister; + +@end /////////////////////////////////////// // Memory Management -- cgit v1.2.3