Transcript Objective-C
MORE on classes in …..
OOP terminology in Objective-C
Class:
defines the grouping of data and code
type of entity
Object or Instance:
a specific instantiation of a class with its own state (class
variables values)
Method:
a “function/operator” that an object knows how to perform
Instance Variable:
this is what we call class variable in other OOP languages
Objective-C
as
an
OOP
lang
Strict superset of C
Mix C with ObjC
Or even C++ with ObjC (usually referred to as ObjC++)
A very simple language, but some new syntax
Single inheritance, classes inherit from one and
only one superclass
Protocols define behavior that cross classes
Dynamic runtime
Loosely typed, if you’d like
More
on
Objective-C
Syntax:
What’s most confusing about Objective-C?
• Most class names start with NS: NSString, NSObject
• Parameter lists are not comma delimited and method
•
•
•
•
names are interrupted by parameter names and types.
There are too many brackets and colons. :[
Memory Management.
All these @ symbols confuse me.
Both C and Objective-C methods are allowed? Weird.
Objective-C
Class
Methods
Instances/Objects respond to instance methods
- (id)init;
- (float)height;
- (void)walk;
[object walk]
Classes respond to class methods
+ (id)alloc;
+ (id)person;
+ (Person *)sharedPerson;
[ClassName person]
Intro to Objective-C Syntax:
Method Signatures
Key
In Java or C:
void doNothing() {
// nothing
}
int addThree(int x) {
return x + 3;
}
int multiplyThreeParameters(int x, int y, int z) {
return x * y * z;
}
return type
method name
parameter type
parameter name
// note methods with multiple parameters are given in a parameter list
// that is delimited by commas.
Intro to Objective-C Syntax:
Method Signatures
In Objective-C
Key
return type
- (void) doNothing {
method name
// nothing
parameter type
}
parameter name
- (int) addThree:(int) x {
return x + 3;
}
- (int) multiplyThis:(int) x ByThis:(int) y AndThis:(int) z {
return x * y * z;
}
NOTE: methods of Objective-C classes with multiple
parameters have a to delimit the end of the parameter
name and the continuation of the method name.
Actually method name is multiplyThis:ByThis:AndThis
Stop---that was weird---method
name is change of the 3
- (int) multiplyThis:(int) x ByThis:(int) y AndThis:(int) z {
return x * y * z;
}
Method name is
multiplyThis:ByThis:AndThis
Intro to Objective-C Syntax:
Accessing methods of objects
In Java: object.method(param1, param2);
In C++: object->method(param1, param2);
In C: (no objects) method(param1, param2);
In Objective-C: [object
method:param1 method:param2];
Only a space between no comma
Intro to Objective-C Syntax:
Accessing methods of objects
In Objective-C: [object method:param1 method:param2];
Example:
If you have a string:
NSString *msg = @"ALL YOUR BASES BELONG TO US";
And you want to split the sentence into an array of words:
NSArray *words = [msg componentsSeparatedByString: @" "];
// The @ is required for all string literals, and encodes the string using
UTF8
Intro to Objective-C Syntax:
Instantiation
/
Memory
Allocation
In Java:
Object o = new Object();
// Java takes care of garbage collection. In this statement, memory
// is automatically allocated for the new object. Memory is also
// automatically released when the object is no longer in use.
In C:
Object *o = (Object *) malloc(sizeof(Object));
free (o);
In C++:
Object *o = new Object;
delete (o);
Intro to Objective-C Syntax:
Instantiation
In Objective-C:
Object *obj = [[Object alloc] init];
Ways of creating objects
Asking other objects to create objects for you
NSString’s - (NSString *)stringByAppendingString:(NSString *)otherString;
NSString’s & NSArray’s - (id)mutableCopy;
NSArray’s - (NSString *)componentsJoinedByString:(NSString *)separator;
Not all objects handed out by other objects are newly created
NSArray’s - (id)lastObject;
NSArray’s - (id)objectAtIndex:(int)index;
Unless the method has the word “copy” in it, if the object already exists, you get a pointer to
it.
If the object does not already exist (like the 3 examples above), then you’re creating.
Using class methods to create objects
NSString’s + (id)stringWithFormat:(NSString *)format, ...
UIButton’s + (id)buttonWithType:(UIButtonType)buttonType;
NSMutableArray’s + (id)arrayWithCapacity:(int)count;
NSArray’s + (id)arrayWithObject:(id)anObject;
Ways of creating objects –cont.
Allocating and initializing an object from scratch
Doing this is a two step process: allocation, then initialization.
Both steps must happen one right after the other (nested one inside the other, in
fact).
Examples:
NSMutableArray *stack = [[NSMutableArray alloc] init];
CalculatorBrain *brain = [[CalculatorBrain alloc] init];
About Allocating
Heap allocation for a new object is done by the NSObject class method + (id)alloc
It allocates enough space for all the instance variables (e.g., the ones created by
@synthesize).
About Initializing
Classes can have multiple, different initializers (with arguments) in addition to
plain init.
If a class can’t be fully initialized by plain init, it is supposed to raise an exception
in init.
NSObject’s only initializer is init.
Ways of creating objects –cont.
More complicated init methods
If an initialization method has arguments, it should still start with the four letters
init
Example: - (id)initWithFrame:(CGRect)aRect; // initializer for UIView
UIView *myView = [[UIView alloc] initWithFrame:thePerfectFrame];
Examples of multiple initializers with different
arguments
From NSString:
- (id)initWithCharacters:(const unichar *)characters length:(int)length;
- (id)initWithFormat:(NSString *)format, ...;
- (id)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding;
Classes must designate an initializer for subclassers
This is the initializer that subclasses must use to initialize themselves in their
designated initializer.
Static typing of initializers
For subclassing reasons, init methods should be typed to return id (not statically
typed)
Callers should statically type though, e.g., MyObject *obj = [[MyObject alloc]
init];
Creating you own init
Creating your own initialization method
Super initializer can return nil if it failed to initialize.
Example ---.m file
@implementation MyObject
- (id)init
{
self = [super init]; // call our super’s designated initializer
if (self) {
// initialize our subclass here
}
return self;
}
@end
Intro to Objective-C Syntax:
Classes
In Java, students can define and implement a class in a single .java file.
In C++, students define a class and methods in a .h header file and
implement the methods in a .c file.
In Objective-C, students define a class and its methods in a .h header
file and implement the methods in a .m file.
include
Circle.h
Circle.m
Intro to Objective-C Syntax:
Classes Circle.h
@interface Circle : NSObject {
// instance variables
double radius = 1.0;
}
// Class methods
+(double) getPi;
// Instance methods
-(double) getArea;
Key
class name
superclass
return type
method name
parameter type
parameter name
-(void) setRadius:(double) r;
@end
Optional
parameter
name
Circle.m
#import "Circle.h"
@implementation Circle
+(double) getPi {
return 3.14159265;
}
-(double) getArea {
double pi = [Circle getPi];
return pi * radius * radius;
}
-(void) setRadius:(double) r {
radius = r;
}
@end
Main.m
#import "Circle.h"
// Non Objective-C function; program origin
int main() {
@autoreleasepool
{
Circle *mycirc = [[Circle alloc] init];
[mycirc setRadius:3.0];
double area = [mycirc getArea];
double pi = [Circle getPi];
return 0;
}
}
Classes --- remember
Have both definition file and implementation file :
classname.h and classname.m
Prototyping methods
When declaring or implementing functions for a class,
they must begin with a + or + indicates a “class method” that can only be used by
the class itself. In other words, they’re for private
functions ---like static functions in other languages.
- indicates “instance methods” to be used by the client
program (public functions) –invoked on objects/instance
of class
Class Declaration (Interface)
#import <Cocoa/Cocoa.h>
node.h
@interface Node : NSObject {
Node *link;
int contents;
Class is Node who’s
}
parent is NSObject
+(id)new;
-(void)setContent:(int)number;
{
class variables }
-(void)setLink:(Node*)next;
-(int)getContent;
-(Node*)getLink;
+/- private/public methods
@end
of Class
Class variables are private
Class Definition (Implementation)
#import "node.h”
@implementation Node
+(id)new
{ return [Node alloc];}
-(void)setContent:(int)number
{contents = number;}
-(void)setLink:(Node*)next {
[link autorelease];
link = [next retain];
}
-(int)getContent
{return contents;}
-(Node*)getLink
{return link;}
@end
node.m
Like your C++
.cpp file
>>just give
the methods
here
Creating class instances
ClassName *object = [[ClassName alloc]
init];
OR
ClassName *object= [[ClassName alloc]
initWith*];
Destroying a class
object = nil;
Like NULL in
C ++
Like null in
Java
The underlying system will take care of removing the
object from memory for you automatically.
Note: a lot of programs don’t explicitly set objects to nil
but, is an option for you.
Do you need to test for nill
if (object == nill) //or if (object)
{ //do whatever }
Actually, in Objective-C if an objects is nil and you send
a message (method call) to it does nothing….however,
if you are expecting results and try to use them you
could get in trouble –so checking in this case is
important.
Setting values for class variables
of an object ---- THROUGH
methods
ClassName *object = [[ClassName
alloc] init];
[object setXXXMethod:value1];
[object setYYYYMethod:value2];
Two kinds of methods – calss and
instance methods
Class Method call is like a STATIC method – call on
the class itself
Example for class NSDate –has class method “date” that will return pointer
to an instance of NSDate associated with current date
NSDate *now = [NSDate date];
Instance method is like normal function – call on an
object
Example for class NSDate –has instance method “timeIntervalSince1970 ”
that will return seconds of the date object since 1970
double seconds = [now timeIntervalSince1970];
Method calls uses “Message
syntax”
[receiver message]
[receiver message:argument]
[receiver message:arg1 andArg:arg2]
Example of a Class method to construct and new
object
NSDate *now = [NSDate date];
More Terminology
Message expression
[receiver method: argument]
Message
[receiver method: argument]
Selector
[receiver method: argument]
Method
The code selected by a message
Message/Method call with
multiple
arguments
[ Object methodp1:v1 methodp2:v2 methodp3:v3]
What is the actual method name? It is (yes it is odd!)
methodp1:methodp2:methodp3
Example
NSCalendar *cal = [NSCalendar currentCalendar];
NSUInteger day = [cal ordinalityOfUnit:NSDayCalendarUnit forDate:now];
What is the name of the method ? It is
ordinalityOfUnit:forDate
Nesting
Method
call
[[ Object method1] method 2]
method 1 executed first and on the results method 2 is
executed
Example without nesting
NSCalendar *cal = [NSCalendar currentCalendar];
NSUInteger day = [cal ordinalityOfUnit:NSDayCalendarUnit forDate:now];
Example WITH nesting
NSUInteger day = [[NSCalendar currentCalendar] ordinalityOfUnit:NSDayCalendarUnit forDate:now]
Some arbitrary examples
Person *voter; //assume this exists
[voter castBallot];
int theAge = [voter age];
[voter setAge:21];
if ([voter canLegallyVote]) {
// do something voter-y
}
[voter registerForState:@"CA“ party:@"Independant"];
NSString *name = [[voter spouse] name];
Accessor Methods
Two kinds: setter methods and getter methods -
- used to set and get instance variables.
Example Person.h
@interface Person : NSObject
{
//two instance variables
float heightInMeters;
int weightInKilos;
}
- (void)setHeightInMeters:(float)h; //setter instance method
- (void)setWeightInKilos:(int)w; //setter instance method
- (void)weightInKilos; //getter instance method
- (void)heightInMeters; //getter insance method
- (float) bodyMassIndex; //instance method
@end
NOTE: the
convention of
naming the setter
methods as
setVariableName
NOTE: the
convention of
naming the getter
methods same as
the variable they
access
Accessor Methods
Example Person.m
@implementation Person
- (float) heightInMeters
{ return heightInMeters; }
- (int) weightInKilos
{ return weightInKilos; }
- (void) setHeightInMeters:(float)h
{ heightInMeters = h; }
- (void) setWeightInKilos:(int)w
{ weightInKilos = w;}
- (float) bodyMassIndex
{ return weightInKilos / (heightInMeters * heightInMeters); }
@end
Lets use our Accessor Methods
Example main.m
Int main(int argc, const char * argv[])
{
@autoreleasepool {
//Create an instance of Person
Person *person = [[Person alloc] init];
//Give instance variables some values
[person setWeightInKilos:96];
[person setHeightInMeters:1.8];
//Call bodyMassIndex method
float bmi = [person bodyMassIndex];
NOTE: %f mean
insert float value,
%d is an integer
value --- same as
you see in printf
for C
//print out
NSLog(@”person (%d, %f) has a BMI of %f”,
[person weightInKilos], [person heightInMeters], bmi);
Properties --simple way to create
accessor
methods
Declare in one line the getter and setter methods for a
variable
Example -- new Person.h
In Person.h add
@property
@interface Person : NSObject
{
//two instance variables
float heightInMeters;
int weightInKilos;
}
@property float heightInMeters; //will create setter and getter method for this var
@property float weightInKilos; //will create setter and getter method for this var
- (float) bodyMassIndex; //instance method
@end
Properties --just have the
@property
Declare in one line the getter and setter methods for a
variable
Example -- new Person.h
@interface Person : NSObject
{
//don’t need to declare the variables here
// ---they are done with @property
}
@property float heightInMeters; //will create setter and getter method for this var
@property float weightInKilos; //will create setter and getter method for this var
- (float) bodyMassIndex; //instance method
@end
Properties
--continued
Use @synthisize annotation
new Person.m
#import “Person.h”
@implementation Person
@synthesize heightInMeters, weightInKilos;
- (float) bodyMassIndex
{ return weightInKilos / (heightInMeters * heightInMeters); }
Now in .m file
must add
@synthesize
annotation
Do not need to
create the
methods
Properties can take paramenters
@property (a1,a2,*) var
Example @property (nonatomic, readonly, strong) NSString *itemName;
nonatomic / atomic = dealing with threading
nonatomic = (YOU USE THIS FOR IOS), not thread-safe
NOTE: no problem if this is UI code because all UI code
happens on the main thread of the application.
atomic = (don’t do this for iOS), thread safe, default
readwrite/readonly
readwrite= default value, declares both a setter and a getter.
readonly =means only create setter method.
weak/strong/assign = dealing with memory management
strong= strong reference to object stored in variable –see ARC
weak = weak reference to object stored in variable –see ARC
assign = default for variables that are primitive data types
Keyword --self
self is like “this” in other OOP languages
//some code inside a method of a class
float h = [self heightInMeters]; //method calss to getter for the variable heightInMeters
//another example a method in a class that adds itself (object) to an array that is passed
-(void) addYourselfToArrayNSMutableArray *) theArray
{ [theArray addObject:self]; }
Inheritence
In .h file
@interface ClassName : ParentClass
{
//class variables
}
//methods
@end
Example of Inheritance
Create class Employee that has Person as parent and
adds class variable of an employee id
Employee.h file
#import “Person.h”
@interface Employee : Person
{
int employeeID;
}
@property int employeeID; //remember short cut to declare accessor methods
// for employeeID class variable
@end
Child
class
Can access Parent’s methods and variables
Overriding methods
//Employee .m file
//override the
#import “Employee.h”
@implementation Employee
@synthesize employeeID;
methods
- (float) bodyMassIndex
{ return 19.0; }
//remember this genearteds the setemployeeID() and employeeID()
//overridden method of previous Person parent class
@end
super = keyword to mean parent class
- (float) bodyMassIndex //overridden method of previous Person parent class
{ float normalBMI = [super bodyMassIndex] ; //first call Person’s bodyMassIndex method
return normalBMI*0.9;
}
Instance variables typically in one
of 4 categories
Primitive data types
int age;
float number;
Object-type attributes
NSString myName;
NSNumber
To-one relationship = point to a single “complex” object
Employee top_Employee;
Person spouse;
To-many relationships = these are collections (objects or data)
NSMutableArray *friends;
NSArray *emails;
Class Example with some different
“kinds” of instance vars
#import “Person.h”
Employee.h
@interface Employee : Person
{
int employeeID;
//primitive data
NSString *lastName; //object type
Person *spouse;
//To-one more complex object
NSMutableArray *children; //To-many collections
}
IMPORTANT
//method declarations *****
Have you noticed that object
instance variables are always
@end
Pointers to objects.
STOP: huh? Variables are always
pointers to Objects
Objects don’t live inside other objects.
You only points from one object to another
MePerson -> spouse (another Person)
Result: you end up with a lot of distinct objects in your
program’s memory
Luckily we have Automatic Reference Counting for our iOS
programs to take care of memory leaking and getting rid of no
longer needed objects!!! Yes!
Object Typing
Suppose have Vehicle class and child Ship class
@interface Vehicle
- (void)move;
@end
@interface Ship : Vehicle
- (void)shoot;
@end
Ship *s = [[Ship alloc] init];
[s shoot];
[s move];
Vehicle *v = s;
[v shoot]; //THIS CAUSES a COMPILER WARNING –but not a runtime error
Object Typing
Suppose have Vehicle class and child Ship class
id obj = ...;
[obj shoot]; //This is NOT a compiler warning
The compiler knows that the method shoot exists,
•possible that obj might respond to it --- NO compiler warning
•not typed obj enough for the compiler to be sure it’s wrong.
Will crash at runtime if obj is not a Ship
(unless is an object of some other class that implements a
shoot method).
Object Typing
Suppose have Vehicle class and child Ship class
id obj = ...;
[obj someMethodNameThatNoObjectAnywhereRespondsTo];
has never heard of this method.
COMPILER WARNING
Object Typing
Suppose have Vehicle class and child Ship class
NSString *hello = @”hello”;
[hello shoot];
The compiler knows that NSString objects do not respond to
shoot.
crash at runtime.
COMPILER WARNING
Object Typing
Suppose have Vehicle class and child Ship class
NSString *hello = @”hello”;
Ship *helloShip = (Ship *)hello;
[helloShip shoot];
We are “casting” here.
The compiler thinks we
know what we’re doing.
No compiler error as
helloShip is thought to be
a ship.. HOWEVER, it is
not so, RUNTIME ERROR
NSObject
Base class for pretty much every object in the iOS SDK
Methods
- (NSString *)description
is a useful method to override (it’s %@ in NSLog()).
- (id)copy
not all objects implement mechanism (raises exception if
not)
- (id)mutableCopy
not all objects implement mechanism (raises exception if
not)
linkList class
#import "linkList.h"
@implementation linkList
+(id)new
{return [linkList
alloc];}
-(void)insert:(int)value {
id temp = [Node new];
[temp setContent:value];
[temp setLink:head];
head = [temp retain];
[temp release];
}
Class linkList is child of
previous Node class
linkList.m
-(void)append:(int)value {
id last = [head getLink];
while ([last getLink] !=
nil)
{last = [last getLink];}
id temp = [Node new];
[temp setContent:value];
[last setLink:temp];
[temp release];
}
-(void)remove {
id temp = head;
head = [head getLink];
[temp release];
}
-(int)getValue {
return [head getContent];}
@end
Remember alloc creates the
object in memory
Stack class
#import "stack.h”
#import "linkList.h”
@interface Stack : linkList
@implementation Stack
{}
+(id)new
{return [Stack alloc];}
+(id)new;
-(void)push:(int)value;
-(void)push:(int)value
-(int)pop;
{[self insert:value];}
@end
stack.h
-(int)pop {
int ret = [self getValue]; //getValue metho
of parent linkList
[self remove];
//remove method of parent
linkList
return ret;
}
stack.m
@end
Self is like the C++/Java word
this.
new is the same as in C++/Java
Example: main.m
#import "stack.h”
int main(){
Stack *s = [Stack
[s push:1];
[s push:2];
printf("%d\t", [s
[s push:3];
printf("%d\t", [s
printf("%d\t", [s
[s release];
return 0;
}
new];
main.c
pop]);
pop]);
pop]);
$ gcc -x objective-c node.m linkList.m stack.m main.c -framework Cocoa -o
stackTest
$./stackTest
2 3 1
Note only need to import “stack.h” because
stack imports LinkList.h which imports Node.h
which imports cocoa.h