Presentation is loading. Please wait.

Presentation is loading. Please wait.

suppose you had Bumblebee, Jet, and Bird classes. All three, although unrelated, implement the flying behavior, and so you could say they are each a Flyer.

Similar presentations


Presentation on theme: "suppose you had Bumblebee, Jet, and Bird classes. All three, although unrelated, implement the flying behavior, and so you could say they are each a Flyer."— Presentation transcript:

1

2 suppose you had Bumblebee, Jet, and Bird classes. All three, although unrelated, implement the flying behavior, and so you could say they are each a Flyer. Also notice that you could shoot all three with a gun, and so you could also say they are Shootable. In both situations you are using a concept to group unrelatedobjects based upon behaviors. Protocols model these types of situations. A class that wishes to adopt a protocol must implement the methods declared by the protocol. By requiring the adopting class to implement methods, a protocol forms a contract. That contract ensures the runtime that a class that adopts a protocol implements the methods declared by the protocol.

3 A protocol’s syntax is similar to a class’ interface. But unlike when writing a class, you only create a header file and do not create an implementation. A protocol begins with the @protocol compiler directive and ends with the @end compiler directive. Between the two compiler directives go any method declarations you wish an adopting class to implement. @protocol@end @protocol@protocol Hopper - (void) hop; - (BOOL) setHopDistance: (long long) distance @end

4 Classes adopt protocols. For instance, a Frog class might implement the Hopper protocol. For Frog to adopt Hopper, it must first import the Hopper.h header file. It then includes Hopper in its @interface compiler directive.@interface @interface Frog: Amphibian A frog is an amphibian, and so it inherits from its Amphibian parent class. Following the parent class is the protocol the frog adopts. The protocol’s name is surrounded by angle brackets.

5 1.Create a View-based application named SimpleFlyer. 2.Create a new C header file called Flyer.h. 3.Modify Flyer.h to be a Flyer protocol that declares a “fly” method. 4. Create three new Objective-C classes named Bumblebee, Bird, and Jet. Change all three so that they adopt the Flyer protocol

6 @protocol Flyer - (NSString *) fly; @end Bumblebee.m #import "Bumblebee.h" @implementation Bumblebee - (NSString *) fly { return @"flying bumblebee..."; } @end Bumblebee.h #import #import "Flyer.h" @interface Bumblebee : NSObject { } @end

7 Bird.h #import #import "Flyer.h" @interface Bird : NSObject { } @end Bird.m #import "Bird.h" @implementation Bird - (NSString *) fly { return @"flying bird..."; } @end Jet.h #import #import "Flyer.h" @interface Jet : NSObject { } @end Jet.m #import "Jet.h" @implementation Jet - (NSString*) fly { return @"flying jet..."; } @end

8 5. Modify SimpleFlyerViewController.h so that it knows about all three classes and the protocol by using the @class and @protocol precompiler directives. Also declare a callFly method and create three properties for each of the three classes. Also create a changeLabel method and be certain you precede the method with the IBAction keyword rather than void.@class @protocol SimpleFlyerViewController.h #import @protocol Flyer; @class Jet; @class Bird; @class Bumblebee @interface SimpleFlyerViewController : UIViewController { Bumblebee * myBee; Bird * myBird; Jet * myJet; IBOutlet UILabel * myLabel; } @property (nonatomic,retain) Bumblebee * myBee; @property (nonatomic,retain) Bird * myBird; @property (nonatomic,retain) Jet * myJet; @property (nonatomic,retain) UILabel * myLabel; - (IBAction) changeLabel: (id) sender; - (NSString*) callFly: (id ) aFlyer; @end 6. Create an IBOutlet for a UILabel and name the property myLabel.

9 7. Modify SimpleFlyerViewController.m so that it synthesizes the properties and implements the callFly method Do not forget to import the classes from the interface. SimpleFlyerViewController.m #import "SimpleFlyerViewController.h" #import "Flyer.h" #import "Bumblebee.h" #import "Bird.h" #import "Jet.h" @implementation SimpleFlyerViewController @synthesize myBee; @synthesize myBird; @synthesize myJet; @synthesize myLabel; static int clicks = 0; - (IBAction) changeLabel: (id) sender { if(clicks == 0) { self.myLabel.text = [self callFly:self.myBee]; } else if(clicks == 1) { self.myLabel.text = [self callFly:self.myBird]; } else { self.myLabel.text = [self callFly:self.myJet]; } clicks++; } - (NSString *) callFly: (id ) aFlyer { return [aFlyer fly]; } - (void) viewDidLoad { [super viewDidLoad]; self.myBee = [[Bumblebee alloc] init]; self.myBird = [[Bird alloc] init]; self.myJet = [[Jet alloc] init]; } - (void)dealloc { [self.myJet release]; [self.myLabel release]; [self.myBee release]; [self.myBird release]; [super dealloc]; } @end

10 8.Double-click SimpleFlyerViewController.xib to open it in Interface Builder. 9.Add a button to the view’s canvas. Double-click the button and change its title to Fly. 10.Add a label to the view’s canvas and resize the label 11.Connect the File’s Owner myLabel outlet to the label Remember, the“outlet” term is simply shorthand for referring to the IBOutlet

11

12 12.Connect the File’s Owner callFly: action to the button’s Touch Up Inside event 13. Save and exit Interface Builder.

13 Properties and Protocols Any classes that then wish to adopt the protocol either must implement custom accessor methods or must synthesize the property. A property’s syntax in a protocol is similar to an interface, only you do not declare an instance variable. @protocol@protocol Countable @property@property (nonatomic, retain) NSNumber * maximumDigit; @end By declaring a property in a protocol, you are informing the compiler that implementing classes must either synthesize the property or create custom accessor methods. But note, any class implementing the protocol must synthesize the property and declare the property as an instance variable in the class’ header.

14 Singer.h @protocol Singer @property (nonatomic,retain) NSString * singerName; - (void) sing; @end For Example Tenor.h #import #import "Singer.h" @interface Tenor : NSObject { NSString * singerName; } @end Tenor.m #import "Tenor.h" @implementation Tenor @synthesize singerName; - (void) sing { NSLog(@"%@, the singing tenor...", self.singerName); } @end

15 SingingFool.m #import #import "Tenor.h" #import "Singer.h" int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Tenor * myTenor = [[[Tenor alloc] init] autorelease]; myTenor.singerName = @"Jameserotti"; [myTenor sing]; [pool drain]; return 0; } Jameserotti, the singing tenor... OutPut

16 Optional Methods Objective-C allows developers considerable flexibility. Protocols can also declare optional methods that adopters are not required to implement. @protocol@protocol Fighter @required -(void) punch; -(void) kick; @optional - (void) cry; @end The @required compiler directive is the default; methods without a preceding compiler directive are assumed required.@required

17 If you wish to call an optional protocol method in another method such as hitInFace, you must check for the method’s existence in the adopting class. -(void) hitInFace: (id ) aFighter { if([aFighter respondsToSelector:@selector(cry)])respondsToSelector:@selector(cry)]) { [aFighter cry]; } The easiest way to ensure a class responds to an optional protocol method is through the respondsToSelector: method.

18 Eater.h @protocol Eater @required //default - (void) eat; @optional - (void) belch; @end Glutton.h #import #import "Eater.h" @interface Glutton : NSObject { } @end Glutton.m #import "Glutton.h" @implementation Glutton - (void) eat { NSLog(@"glutton eating..."); } - (void) belch { NSLog(@"glutton belching..."); } @end Socialite.h #import #import "Eater.h" @interface Socialite : NSObject { } @end

19 Socialite.m #import "Socialite.h" @implementation Socialite - (void) eat { NSLog(@"socialite is eating..."); } @end EatingExample.m #import #import "Glutton.h" #import "Socialite.h" int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Glutton * myGlutton = [[[Glutton alloc] init] autorelease]; Socialite * mySocialite = [[[Socialite alloc] init] autorelease]; [myGlutton eat]; [mySocialite eat]; if([myGlutton respondsToSelector:@selector(belch)]) { [myGlutton belch]; } if([mySocialite respondsToSelector:@selector(belch)]) { [mySocialite belch]; } [pool drain]; return 0; }

20 Protocols and id - (void) doAttach: (id) aFloater; - (void) detach: ( ) aFloater; - (void) sinkAFloater: (id ) aFloater; Using id Only One way you can use a protocol as a method parameter is by using the id keyword. The id type is a generic pointer that can point to any object. -(void) doAttach: (id) aFloater - { if([aFloater conformsToProtocol:@protocol(Floater)]) { [aFloater attach];conformsToProtocol:@protocol(Floater)]) }

21 Using id with a Protocol Restriction You can restrict a method’s parameter so that it can still take an id, but only if that id’s object adopts the specified protocol. The following detach method illustrates. -(void) detach: ( ) aFloater { [aFloater detach]; } In detach the id parameter is implicit. The method takes any object provided the object implements the Floater protocol. You can also make the id explicit, as the following sinkAFloater method illustrates. -(void) sinkAFloater: (id ) aFloater { [aFloater sink]; }

22 Adopting Multiple Protocols Objective-C allows objects to adopt more than one protocol. When a class adopts more than one protocol, you list the protocols as a comma- separated list. @interface@interface Duck : NSObject @interface@interface Duck : NSObject Swimmer.h @protocol Swimmer - (NSString *) swim; @end Duck.h #import #import "Flyer.h" #import "Swimmer.h" @interface Duck : NSObject { } @end

23 Duck.m #import "Duck.h" @implementation Duck - (NSString *) fly { return @"flying duck..."; } - (NSString *) swim { return @"swimming duck..."; } @end SimpleFlyerViewController.h #import @class Duck; @class Jet; @class Bumblebee; @class Bird; @interface SimpleFlyerViewController : UIViewController { Bumblebee * myBee; Bird * myBird; Jet * myJet; Duck * myDuck; IBOutlet UILabel * myLabel; } @property (nonatomic,retain) Bumblebee * myBee; @property (nonatomic,retain) Bird * myBird; @property (nonatomic,retain) Jet * myJet; @property (nonatomic,retain) Duck * myDuck; @property (nonatomic,retain) UILabel * myLabel; - (IBAction) changeLabel: (id) sender; - (NSString*) callFly: (id ) aFlyer; - (void) callSwim: (id) aFlyer; @end

24 SimpleFlyerViewController.m #import "SimpleFlyerViewController.h" #import "Flyer.h" #import "Bumblebee.h" #import "Bird.h" #import "Jet.h" #import "Duck.h" @implementation SimpleFlyerViewController @synthesize myBee; @synthesize myBird; @synthesize myJet; @synthesize myLabel; @synthesize myDuck; static int clicks = 0; - (IBAction) changeLabel: (id) sender { id myObject = nil; if(clicks == 0) { self.myLabel.text = [self callFly:self.myBee]; myObject = self.myBee; } else if(clicks == 1) { self.myLabel.text = [self callFly:self.myBird]; myObject = self.myBird; } else if(clicks == 2) { self.myLabel.text = [self callFly:self.myJet]; myObject = self.myJet; } else { self.myLabel.text = [self callFly:self.myDuck]; myObject = self.myDuck; } [self callSwim:myObject]; clicks++; } - (NSString *) callFly: (id ) aFlyer { return [aFlyer fly]; } - (void) callSwim: (id) aFlyer { if ( [aFlyer conformsToProtocol:@protocol(Swimmer)] ) { NSLog([aFlyer swim]); } - (void) viewDidLoad { [super viewDidLoad]; self.myBee = [[[Bumblebee alloc] init] autorelease]; self.myBird = [[[Bird alloc] init] autorelease]; self.myJet = [[[Jet alloc] init] autorelease]; self.myDuck = [[[Duck alloc] init] autorelease]; } - (void)dealloc { [self.myJet release]; [self.myBee release]; [self.myBird release]; [self.myDuck release]; [self.mylabel release]; [super dealloc]; } @end

25 Extending Protocols The syntax for a protocol extending another protocol is as follows: @protocol@protocol Swimmer Sinkable.h @protocol Sinkable - (void) sink; @end Floater.h #import "Sinkable.h" @protocol Floater - (void) floatMe; @end Swimmer.h #import "Floater.h" @protocol Swimmer -(void) swim; @end Driftwood.h #import #import "Floater.h" @interface Driftwood : NSObject { } @end

26 Driftwood.m #import "Driftwood.h" @implementation Driftwood -(void) floatMe { NSLog(@"driftwood floating..."); } -(void) sink { NSLog(@"driftwood sinking...."); } @end Duck.h #import #import "Swimmer.h" @interface Duck : NSObject { } @end Duck.m #import "Duck.h" @implementation Duck - (void) swim { NSLog(@"duck swimming..."); } -(void) floatMe { NSLog(@"duck floating...."); } - (void) sink { NSLog(@"duck sinking...."); } @end LeadWeight.h #import #import "Floater.h" @interface LeadWeight : NSObject { } - (void) sinkASinkable: (id ) aSinkable; @end

27 LeadWeight.m #import "LeadWeight.h" @implementation LeadWeight - (void) sinkASinkable: (id ) aSinkable; { [aSinkable sink]; } @end DriftwoodDuck.m #import #import "Duck.h" #import "Driftwood.h" #import "LeadWeight.h" int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Duck * myDuck = [[[Duck alloc] init] autorelease]; [myDuck floatMe]; [myDuck swim]; Driftwood * myDriftwood = [[[Driftwood alloc] init] autorelease]; [myDriftwood floatMe]; LeadWeight * myWeight = [[[LeadWeight alloc] init] autorelease]; [myWeight sinkASinkable:myDriftwood]; [myWeight sinkASinkable:myDuck]; [pool drain]; return 0; } Debugger console logging duck floating.... duck swimming... driftwood floating... driftwood sinking.... duck sinking....

28 Categories When you want to add methods to a class, you typically extend it. However this solution isn't always perfect, especially if you want to rewrite the functionality of a class that you don't have the source code to. Categories allow you to add functionality to already existing classes without extending them. Ruby also has similar functionality to this.

29 Categories allows programmer to add functionality to already existing classes without extending them. BaseClass.hBaseClass.m #import @interface BaseClass : NSObject { int num1, num2; } -(void)set :(int) x and: (int) y; -(int)add; -(int)sub; @end #import"BaseClass.h" @implementation BaseClass -(void)set :(int) x and: (int) y { num1 = x; num2 = y; } -(int)add { return num1+num2; } -(int)sub { if(num1>num2){ return num1-num2; } else return num2-num1; } @end

30 SubClass.hSubClass.m #import"BaseClass.h“ @interface BaseClass(Category) - (void)show:(int)x; @end #import"SubClass.h“ @implementation BaseClass(BaseClass) -(void)show:(int)x { printf("Result is : %d \n",x); } @end #import"BaseClass.m“ #import"SubClass.m“ #import int main() { BaseClass *obj = [[BaseClass alloc] init]; [obj set:10 and:8]; [obj show:[obj add]]; [obj show:[obj sub]]; [obj release]; return 0; } Result is : 18 Result is : 2

31 1.There is the two @implementation and @interface lines: @interface Fraction (Math) and @implementation Fraction (Math). 2.There can only be one category with the same name. Additional cateogies may be added on with different but unqiue names. 3.Categories can't add instance variables. 4.Categories are useful for creating private methods. Since Objective-C has no notion of private/protected/public methods like java does, one has to create categories that hide such functionality. The way this is done is by moving the private methods from your class's header (.h) file to the implementation file (.m)

32 BetterDuck+Duck.h #import #import "Duck.h" @interface Duck (BetterDuck) -(void) quack; @end BetterDuck+Duck.m #import "BetterDuck+Duck.h" @implementation Duck (BetterDuck) - (void) quack { NSLog(@"quack..."); } @end

33 DriftwoodDuck.m #import //#import "Duck.h" #import "Driftwood.h" #import "LeadWeight.h" #import "BetterDuck+Duck.h" int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Duck * myDuck = [[[Duck alloc] init] autorelease]; [myDuck float]; [myDuck swim]; Driftwood * myDriftwood = [[[Driftwood alloc] init] autorelease]; [myDriftwood float]; LeadWeight * myWeight = [[[LeadWeight alloc] init] autorelease]; [myWeight sinkASinkable:myDriftwood]; [myWeight sinkASinkable:myDuck]; Duck * myBetterDuck = [[[Duck alloc] init] autorelease]; [myBetterDuck float]; [myBetterDuck swim]; [myBetterDuck quack]; [pool drain]; return 0; }

34 Posing

35 It enable programmer to pose subclass to super class globally. When subclass posed on super class method which are same in both classes are override with the subclass methods. BaseClass.h BaseClass.m #import @interface BaseClass : NSObject { int num1, num2; } -(void)set :(int) x and: (int) y; -(int)add; -(int)sub; -(void)show:(int)x; @end #import"BaseClass.h“ @implementation BaseClass -(void)set :(int) x and: (int) y { num1 = x; num2 = y; } -(int)add { return num1+num2; } -(int)sub { if(num1>num2) { return num1-num2; } Else return num2-num1; } -(void)show:(int)x { printf("Base class result : %d \n",x); } @end

36 SubClass.h SubClass.m #import"BaseClass.h“ @interface SubClass : BaseClass -(void)show:(int)x; @end #import"SubClass.h“ @implementation SubClass -(void)show:(int)x { printf("Sub class result : %d \n",x); } @end

37 #import"BaseClass.m" #import"SubClass.m" #import int main() { // create base class object. BaseClass *obj1 = [[BaseClass alloc] init]; [obj1 set:10 and:8]; [obj1 show:[obj1 add]]; [obj1 show:[obj1 sub]]; // pose subclass to baseclass. [SubClass poseAsClass: [BaseClass class]]; // create base class object after posing. BaseClass *obj2 = [[BaseClass alloc] init]; [obj2 set:11 and:6]; [obj2 show:[obj2 add]]; [obj2 show:[obj2 sub]]; / / free memory [obj1 release]; [obj2 release]; return 0; } we have two classes BaseClass and SubClass. Method show() is defined in both class but with different message. Before posing when we create object of base class, show method will show the output according to the base class but after posing it will display output from show method defined in sub class. Base class result : 18 Base class result : 2 Sub class result : 17 Sub class result : 5


Download ppt "suppose you had Bumblebee, Jet, and Bird classes. All three, although unrelated, implement the flying behavior, and so you could say they are each a Flyer."

Similar presentations


Ads by Google