类和对象
1. 类定义
@interface Person : NSObject
{
}
@end
2. 成员变量
@private
NSString *_name; //在ObjC中推荐成员变量名以_开头
int _age;
@protected
NSString *_nation;
@public
float height;
3. 方法和属性
说明:参数类型、返回值类型需要放到()中、冒号是方法名的一部分
h
//声明一个动态方法,没有返回值
-(void)setName:(NSString *)name;
//声明一个静态方法,没有返回值
+(void)showMessage:(NSString *)info;
m
#import "Person.h"
@implementation Person
//实现一个动态方法
-(void)setName:(NSString *)name{
_name=name;
}
//实现一个静态方法
+(void)showMessage:(NSString *)info{
NSLog(@"%@",info);
}
@end
4. getter/setter
//实现age的setter、getter方法
-(int)age{
return _age;
}
-(void)setAge:(int)age{
_age=age;
}
5. 类的初始化和方法的调用
Person *p=[Person alloc];
p=[p init];
//上面两句代码可以直接写成:Person *p=[[Person alloc] init];
//还可以写成:Person *p=[Person new];
//成员变量调用
p->height=1.72;
NSLog(@"height=%.2f",p->height);//结果:height=1.72
//方法调用
[p setName:@"Kenshin"];
//属性调用
p.age=28; //等价于:[p setAge:28];
int age=p.age;//等价于:age=[p age];
NSLog(@"age=%i",age); //结果:age=28
6. @propert和@synthesize
6.1 如果只声明一个属性a,不使用@synthesize实现:编译器会使用_a作为属性的成员变量(如果没有定义成员变量_a则会自动生成一个私有的成员变量_a;如果已经定义了成员变量_a则使用自定义的成员变量_a。注意:如果此时定义的成员变量不是_a而是a则此时会自动生成一个成员变量_a,它跟自定义成员变量a没有任何关系);
6.2 如果声明了一个属性a,使用@synthesize a进行实现,但是实现过程中没有指定使用的成员变量(例如上面birthday):则此时编译器会使用a作为属性的成员变量(如果定义了成员变量a,则使用自定义成员变量;如果此时没有定义则会自动生成一个私有的成员变量a,注意如果此时定义的是_a则它跟生成的a成员变量没有任何关系);
6.3 如果声明了一个属性a,使用@synthesize a=_a进行实现,这个过程已经指定了使用的成员变量:此时会使用指定的成员变量作为属性变量;
有了上面的总结,相信理解上面的代码并不难,通常在实际开发过程中我们要么直接在@property中声明不使用@synthesize;要么使用过程中指定具体的成员变量。
此外再次强调一下,通过上面的方式定义变量的本质还是生成对应的gettter、setter方法(只是这个步骤编译器帮你完成了),如果通过@property定义了属性,同时在.m中又自定义实现了对应方法,则会使用自定义方法。
#import <Foundation/Foundation.h>
#.h
@interface Person : NSObject{
}
@property NSString *birthday;
#.m
#import "Person.h"
@implementation Person
@synthesize birthday;
-(void)printInfo{
NSLog(@"_birthday=%@",_birthday);
}
@end
7. self
self不仅可以表示当前对象还可以表示类本身,也就是说它既可以用在静态方法中又可以用在动态方法中。
Perosn.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property NSString *name;
@property int age;
-(void)setName:(NSString *)name andAge:(int)age;
+(void)showMessage;
@end
Person.m
#import "Person.h"
@implementation Person
-(void)setName:(NSString *)name andAge:(int)age{
self.name=name;
self.age=age;
}
+(void)printInfo{
NSLog(@"Hello,World!");
}
+(void)showMessage{
[self printInfo];
}
@end
8. 构造方法
Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property NSString *name;
@property int age;
-(id)initWithName:(NSString *)name andAge:(int )age;
@end
Person.m
#import "Person.h"
@implementation Person
//自定义构造方法
-(id)initWithName:(NSString *)name andAge:(int)age{
if(self=[super init]){ //super代表父类
self.name=name;
self.age=age;
}
return self;
}
@end
9. 申请内存
Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property NSString *name;
@property int age;
-(id)initWithName:(NSString *)name andAge:(int )age;
+(id)personWithName:(NSString *)name andAge:(int )age;
@end
Person.m
#import "Person.h"
@implementation Person
//自定义构造方法
-(id)initWithName:(NSString *)name andAge:(int)age{
if(self=[super init]){ //super代表父类
self.name=name;
self.age=age;
}
return self;
}
//通过静态方法获得一个对象
+(id)personWithName:(NSString *)name andAge:(int)age{
Person *p=[[Person alloc]initWithName:name andAge:age];
return p;
}
@end
main.m
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
Person *p=[[Person alloc]initWithName:@"Kenshin" andAge:28];
NSLog(@"name=%@,age=%i",p.name,p.age);
//结果:name=Kenshin,age=28
Person *p2=[Person personWithName:@"Kaoru" andAge:27];
NSLog(@"name=%@,age=%i",p2.name,p2.age);
//结果:name=Kaoru,age=27
return 0;
}
10. description方法
在C#中每个类都有一个ToString()方法(java中叫做toString())用于打印一个对象的信息,在ObjC中这个方法叫description,例如在前面的Person类中我们可以重写这个方法用于打印调试
Person.m
#import "Person.h"
@implementation Person
-(NSString *)description{
return [NSString stringWithFormat:@"{name:%@,age:%i}",self.name,self.age];
}
@end
main.m
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
Person *p=[[Person alloc]init];
p.name=@"Kenshin";
p.age=28;
NSLog(@"%@",p);//此时会调用对象description方法返回对应的描述信息
/*结果:
name:Kenshin,age:28}
*/
return 0;
}
注意:
上面NSLog中的格式符是%@,当使用%@输出一个对象时,ObjC会调用个对象的description返回对应的信息进行输出,默认情况下如果我们不重写description方法,输出内容是类名和地址,例如Person则输出“<Person: 0x100202310>
需要强调的是千万不要在description中打印输出self,因为当输出self时会调用该对象的description方法,如此一来就会造成死循环。
11. 继承
Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject{
@protected
NSString *_nation;
}
#pragma mark - 属性
#pragma mark 姓名
@property (nonatomic,copy) NSString *name;
#pragma mark 年龄
@property (nonatomic,assign) int age;
#pragma mark 籍贯
@property (nonatomic,copy) NSString *nation;
#pragma mark - 动态方法
#pragma mark 带有参数的构造函数
-(id)initWithName:(NSString *)name andAge:(int )age;
#pragma mark - 静态方法
#pragma mark 通过静态方法返回一个对象
+(id)personWithName:(NSString *)name andAge:(int )age;
@end
Person.m
#import "Person.h"
@implementation Person
#pragma mark - 动态方法
#pragma mark 带有参数的构造函数
-(id)initWithName:(NSString *)name andAge:(int)age{
if(self=[super init]){ //super代表父类
self.name=name;
self.age=age;
}
return self;
}
#pragma mark - 静态方法
#pragma mark 通过静态方法返回一个对象
+(id)personWithName:(NSString *)name andAge:(int)age{
Person *p=[[Person alloc]initWithName:name andAge:age];
return p;
}
#pragma mark - 重写方法
#pragma mark 重写description
-(NSString *)description{
return [NSString stringWithFormat:@"{name:%@,age:%i}",self.name,self.age];
}
@end
Student.h
#import "Person.h"
@interface Student : Person
#pragma mark - 属性
#pragma mark 分数
@property (nonatomic,assign) float score;
#pragma mark - 动态方法
#pragma mark 带有参数的构造函数
-(id)initWithName:(NSString *)name andAge:(int )age andScore:(float)score;
#pragma mark - 静态方法
#pragma mark 通过静态方法返回一个对象
+(id)studentWithName:(NSString *)name andAge:(int )age andScore:(float)score;
@end
Student.m
//
// Student.m
// ClassAndObject
//
// Created by Kenshin Cui on 14-2-1.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//
#import "Student.h"
@implementation Student
#pragma mark - 动态方法
#pragma mark 带有参数的构造函数
-(id)initWithName:(NSString *)name andAge:(int )age andScore:(float)score{
if(self=[super initWithName:name andAge:age]){
self.score=score;
}
return self;
}
#pragma mark - 静态方法
#pragma mark 通过静态方法返回一个对象
+(id)studentWithName:(NSString *)name andAge:(int)age andScore:(float)score{
Student *s=[[Student alloc]initWithName:name andAge:age andScore:score];
return s;
}
#pragma mark - 重写方法
#pragma mark 重写description
-(NSString *)description{
return [NSString stringWithFormat:@"{name:%@,age:%i,nation:%@,scroe:%.2f}",self.name,self.age,self->_nation,self.score]; //注意这里访问了父类的属性和方法
}
@end
main.m
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"
int main(int argc, const char * argv[]) {
Person *p=[Person personWithName:@"Kenshin" andAge:28];
NSLog(@"p=%@",p);
Student *s=[Student studentWithName:@"Kaoru" andAge:27 andScore:100];
s.nation=@"henan";
NSLog(@"s=%@",s);
return 0;
}
iOS开发系列文章(https://www.cnblogs.com/kenshincui/p/3985090.html)
网友评论