mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2025-05-06 06:48:32 +00:00
Merge branch 'master' of github.com:adambard/learnxinyminutes-docs
This commit is contained in:
commit
159889ca92
@ -5,6 +5,8 @@ contributors:
|
|||||||
filename: coffeescript.coffee
|
filename: coffeescript.coffee
|
||||||
---
|
---
|
||||||
|
|
||||||
|
See also [the CoffeeScript website](http://coffeescript.org/), which has a complete tutorial on CoffeeScript.
|
||||||
|
|
||||||
``` coffeescript
|
``` coffeescript
|
||||||
# CoffeeScript is a hipster language.
|
# CoffeeScript is a hipster language.
|
||||||
# It goes with the trends of many modern languages.
|
# It goes with the trends of many modern languages.
|
||||||
|
@ -430,7 +430,8 @@ distance = 18; // References "long distance" from MyClass implementation
|
|||||||
return @42;
|
return @42;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
- (NSNumber *)secretPrivateMethod {
|
- (NSNumber *)secretPrivateMethod {
|
||||||
return @72;
|
return @72;
|
||||||
}
|
}
|
||||||
@ -444,15 +445,218 @@ distance = 18; // References "long distance" from MyClass implementation
|
|||||||
|
|
||||||
@end // States the end of the implementation
|
@end // States the end of the implementation
|
||||||
|
|
||||||
/*
|
///////////////////////////////////////
|
||||||
* A protocol declares methods that can be implemented by any class.
|
// Categories
|
||||||
* Protocols are not classes themselves. They simply define an interface
|
///////////////////////////////////////
|
||||||
* that other objects are responsible for implementing.
|
// 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.
|
||||||
@protocol MyProtocol
|
// Subclasses are meant to CHANGE functionality of an object while categories instead ADD
|
||||||
- (void)myProtocolMethod;
|
// 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
|
@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 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 (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.
|
||||||
|
|
||||||
|
- (void)washWindows; // Names of the new methods we are adding to our Car object.
|
||||||
|
- (void)wax;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
// @implementation filename: Car+Clean.m (BaseClassName+CategoryName.m)
|
||||||
|
#import "Car+Clean.h" // Import the Clean category's @interface file.
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
// 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
|
||||||
|
// that other objects are responsible for implementing.
|
||||||
|
// @protocol filename: "CarUtilities.h"
|
||||||
|
@protocol CarUtilities <NSObject> // <NSObject> => 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 <CarUtilities> // Name of protocol goes inside <>
|
||||||
|
// You don't need the @property or method names here for CarUtilities. Only @implementation does.
|
||||||
|
- (void)turnOnEngineWithUtilities:(id <CarUtilities>)car; // You can use protocols as data too.
|
||||||
|
@end
|
||||||
|
// The @implementation needs to implement the @properties and methods for the protocol.
|
||||||
|
@implementation Car : NSObject <CarUtilities>
|
||||||
|
|
||||||
|
@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 <CarUtilities>)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) <CarUtilities>
|
||||||
|
// You may implement many protocols: @interface Car : NSObject <CarUtilities, CarCleaning>
|
||||||
|
// 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 <NSObject>
|
||||||
|
|
||||||
|
- (void)beNiceToBrother:(id <Brother>)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 <NSObject>
|
||||||
|
|
||||||
|
- (void)beNiceToSister:(id <Sister>)sister;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
// Memory Management
|
// Memory Management
|
||||||
|
Loading…
Reference in New Issue
Block a user