Download presentation
Presentation is loading. Please wait.
Published byMarvin Bridges Modified over 9 years ago
1
More on Classes Inheritance Copyright © 2012 by Yong-Gu Lee (lygu@gist.ac.kr)
2
More on classes
3
Managing classes on separate files Two files for each class (one for the interface and one for the implementation) Can be too granular
4
Main file // // main.m // FractionTest // // Created by 용구 이 on 12. 4. 3.. // Copyright (c) 2012 년 lygu@gist.ac.kr. All rights reserved. // #import #import "Fraction.h" int main (int argc, const char * argv[]) { @autoreleasepool { Fraction *myFraction = [[Fraction alloc] init]; // set fraction to 1/3 [myFraction setNumerator: 1]; [myFraction setDenominator: 3]; // display the fraction NSLog (@"The value of myFraction is:"); [myFraction print]; } return 0; }
5
Menu for new class
6
Class name
9
Fraction.h
10
Fraction.m
11
Synthesized Accessor Methods You can have your setter and getter methods (collectively known as accessor methods) automatically generated for The first step is to use the @property directive in your interface section to identify your properties. These properties are often your instance variables. In the case of our Fraction class, the two instance variables numerator and denominator fall into this category.
12
@property // // Fraction.h // FractionTest // // Created by 용구 이 on 12. 4. 3.. // Copyright (c) 2012 년 lygu@gist.ac.kr. All rights reserved. // #import @interface Fraction : NSObject @property int numerator, denominator; -(void) print; -(double) convertToNum; @end
13
@synthesize // // Fraction.m // FractionTest // // Created by 용구 이 on 12. 4. 3.. // Copyright (c) 2012 년 lygu@gist.ac.kr. All rights reserved. // #import "Fraction.h" @implementation Fraction @synthesize numerator, denominator; -(void) print { NSLog (@"%i/%i", numerator, denominator); } -(double) convertToNum { if (denominator != 0) return (double) numerator / denominator; else return NAN; } @end
14
Accessing Properties Using the Dot Operator [myFraction numerator] myFraction.numerator The general format here is: instance.property You can use a similar syntax to assign values as well: instance.property = value This is equivalent to writing the following expression:[instance setProperty: value] Previously, you set the numerator and denominator of your fraction to 1/3 using the following two lines of code: [myFraction setNumerator: 1]; [myFraction setDenominator: 3]; Here’s an equivalent way to write the same two lines: myFraction.numerator = 1; myFraction.denominator = 3;
15
Multiple Arguments to Methods A method to set both the numerator and the denominator could be named and used like this: [myFraction setNumerator: 1 andDenominator: 3]; [myFraction setTo: 1 over: 3];
16
Example // // Fraction.h // FractionTest // // Created by 용구 이 on 12. 4. 3.. // Copyright (c) 2012 년 lygu@gist.ac.kr. All rights reserved. // #import @interface Fraction : NSObject @property int numerator, denominator; -(void) print; -(double) convertToNum; -(void) setTo: (int) n over: (int) d; @end
17
// // Fraction.m // FractionTest // // Created by 용구 이 on 12. 4. 3.. // Copyright (c) 2012 년 lygu@gist.ac.kr. All rights reserved. // #import "Fraction.h" @implementation Fraction @synthesize numerator, denominator; -(void) print { NSLog (@"%i/%i", numerator, denominator); } -(double) convertToNum { if (denominator != 0) return (double) numerator / denominator; else return NAN; } -(void) setTo: (int) n over: (int) d { numerator = n; denominator = d; } @end
18
// // main.m // FractionTest // // Created by 용구 이 on 12. 4. 3.. // Copyright (c) 2012 년 lygu@gist.ac.kr. All rights reserved. // #import #import "Fraction.h" int main (int argc, const char * argv[]) { @autoreleasepool { Fraction *myFraction = [[Fraction alloc] init]; [myFraction setTo: 100 over: 200]; [myFraction print]; [myFraction setTo: 1 over: 3]; [myFraction print]; } return 0; }
19
Methods Without Argument Names When creating the name for a method, the argument names are actually optional. For example, you can declare a method like this: -(int) set: (int) n: (int) d; Note that, unlike in previous examples, no name is given for the second argument to the method To invoke the set:: method, you use the colons as argument delimiters, as shown here: [aFraction set: 1 : 3]; -(void) setTo: (int) n over: (int) d
20
Local variables Variables defined within a method is local and destroyed upon exit from the method -(void)reduce { int u = numerator; int v = denominator; int temp; while (v != 0) { temp = u % v; u = v; v = temp; } numerator /= u; denominator /= u; }
21
The static Keyword static int hitCount = 0; -(int) showPage { static int pageCount = 0;... ++pageCount;... return pageCount; }
22
The local static variable would be set to 0 only once when the program started and would retain its value through successive invocations of the showPage method. Note the difference between making pageCount a local static variable and making it an instance variable. In the former case, pageCount could count the number of pages printed by all objects that invoked the showPage method. In the latter case, the variable would count the number of pages printed by each individual object because each object would have its own copy of pageCount.
23
The self keyword -(void) print { [self reduce]; NSLog (@"%i/%i", numerator, denominator); }
24
Inheritance
25
It all begins at the root @interface Fraction: NSObject... @end The class that has no parent is at the top of the hierarchy and is known as a root class. Parent class/Superclass Child class/Subclass
26
Example #import // Simple example to illustrate inheritance #import // ClassA declaration and definition @interface ClassA: NSObject { int x; } -(void) initVar; @end @implementation ClassA -(void) initVar { x = 100; } @end // Class B declaration and definition @interface ClassB : ClassA -(void) printVar; @end @implementation ClassB -(void) printVar { NSLog (@"x = %i", x); } @end int main (int argc, const char * argv[]) { @autoreleasepool { ClassB *b = [[ClassB alloc] init]; [b initVar]; // will use inherited method [b printVar]; // reveal value of x; } return 0; } public
27
Rectangle #import @interface Rectangle: NSObject @property int width, height; -(int) area; -(int) perimeter; @end @implementation Rectangle @synthesize width, height; -(void) setWidth: (int) w andHeight: (int) h { width = w; height = h; } -(int) area { return width * height; } -(int) perimeter { return (width + height) * 2; } @end
28
int main (int argc, char *argv[]) { @autoreleasepool { Rectangle *myRect = [[Rectangle alloc] init]; [myRect setWidth: 5 andHeight: 8]; NSLog (@"Rectangle: w = %i, h = %i", myRect.width, myRect.height); NSLog (@"Area = %i, Perimeter = %i", [myRect area],[myRect perimeter]); } return 0; } [Switching to process 2263 thread 0x0] 2012-04-03 15:33:03.575 porg5[2263:707] Rectangle: w = 5, h = 8 2012-04-03 15:33:03.589 porg5[2263:707] Area = 40, Perimeter = 26
29
Square (inherits Rectangle) @interface Square: Rectangle -(void) setSide: (int) s; -(int) side; @end @implementation Square: Rectangle -(void) setSide: (int) s { [self setWidth: s andHeight: s]; } -(int) side { return width; } @end int main (int argc, char *argv[]) { @autoreleasepool { Square *mySquare = [[Square alloc] init]; [mySquare setSide: 5]; NSLog (@"Square s = %i", [mySquare side]); NSLog (@"Area = %i, Perimeter = %i", [mySquare area], [mySquare perimeter]); } return 0; } 2012-04-03 15:38:35.074 porg5[2329:707] Square s = 5 2012-04-03 15:38:35.075 porg5[2329:707] Area = 25, Perimeter = 20
30
A Point Class and Memory Allocation #import @class XYPoint; @interface Rectangle: NSObject @property int width, height; -(int) area; -(int) perimeter; -(void) setOrigin: (XYPoint *) pt; -(XYPoint *) origin; @end
31
@interface XYPoint: NSObject { int x; int y; } @property int x, y; -(void) setX: (int) xVal andY: (int) yVal; @end @implementation XYPoint @synthesize x, y; -(void) setX: (int) xVal andY: (int) yVal { x = xVal; y = yVal; } @end @implementation Rectangle { XYPoint *origin; } -(void) setOrigin: (XYPoint *) pt { origin = pt; } -(XYPoint *) origin { return origin; } @end
32
Main int main (int argc, char *argv[]) { @autoreleasepool { Rectangle *myRect = [[Rectangle alloc] init]; XYPoint *myPoint = [[XYPoint alloc] init]; [myPoint setX: 100 andY: 200]; [myRect setWidth: 5 andHeight: 8]; myRect.origin = myPoint; NSLog (@"Rectangle w = %i, h = %i", myRect.width, myRect.height); NSLog (@"Origin at (%i, %i)",myRect.origin.x, myRect.origin.y); NSLog (@"Area = %i, Perimeter = %i", [myRect area], [myRect perimeter]); } return 0; } 2012-04-03 16:43:32.838 porg5[2743:707] Rectangle w = 5, h = 8 2012-04-03 16:43:32.869 porg5[2743:707] Origin at (100, 200) 2012-04-03 16:43:32.873 porg5[2743:707] Area = 40, Perimeter = 26 2012-04-03 16:43:32.875 porg5[2743:707] Square s = 5 2012-04-03 16:43:32.876 porg5[2743:707] Area = 25, Perimeter = 20 Program ended with exit code: 0
33
Classes not owning their objects int main (int argc, char *argv[]) { @autoreleasepool { Rectangle *myRect = [[Rectangle alloc] init]; XYPoint *myPoint = [[XYPoint alloc] init]; [myPoint setX: 100 andY: 200]; [myRect setWidth: 5 andHeight: 8]; myRect.origin = myPoint; NSLog (@"Origin at (%i, %i)", myRect.origin.x, myRect.origin.y); [myPoint setX: 50 andY: 50]; NSLog (@"Origin at (%i, %i)", myRect.origin.x, myRect.origin.y); } return 0; } 2012-04-03 16:46:39.838 porg5[2796:707] Origin at (100, 200) 2012-04-03 16:46:39.840 porg5[2796:707] Origin at (50, 50)
34
Classes owning their objects -(void) setOrigin: (XYPoint *) pt { if (! origin) origin = [[XYPoint alloc] init]; origin.x = pt.x; origin.y = pt.y; } The change to the setOrigin: method means that each Rectangle instance now owns its XYPoint instance. Even though it is now responsible for allocating the memory for that XYPoint, it should also now become responsible for releasing that memory. In general, when a class contains other objects, at times you will want to have it own some or all of those objects.
35
Overriding Methods You can’t remove or subtract methods through inheritance. However, you can change the definition of an inherited method by overriding it. A method defined with the same name as that of a parent class replaces, or overrides, the inherited definition. Your new method must have the same return type and take the same number and type of arguments as the method you are overriding.
36
-(void) printVar { // added method NSLog (@"x = %i", x); } @end //////////////////////////// int main (int argc, const char * argv[]) { @autoreleasepool { ClassB *b = [[ClassB alloc] init]; [b initVar]; // uses overriding method in B [b printVar]; // reveal value of x; } return 0; } // ClassA declaration and definition @interface ClassA: NSObject { int x; } -(void) initVar; @end //////////////////////////// @implementation ClassA -(void) initVar { x = 100; } @end // ClassB declaration and definition @interface ClassB: ClassA -(void) initVar; -(void) printVar; @end //////////////////////////// @implementation ClassB -(void) initVar { x = 200; }
37
Abstract classes Sometimes classes are created just to make it easier for someone to create a subclass. For that reason, these classes are called abstract classes or, equivalently, abstract superclasses. Methods and instance variables are defined in the class, but no one is expected to actually create an instance from that class. For example, consider the root object NSObject. Can you think of any use for defining an object from that class? The abstract superclass gives a common interface for working with all types of subclassses.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.