您的位置:首页 > 其它

ObjC第二节:属性声明、类的组合

2015-08-11 20:30 399 查看
属性声明、类的组合
1、属性声明

     1.1 声明属性让编译器自动合成setter和getter方法,使用关键字@property和@synthesize

     1.2 在头文件中,@property int count; 等价于- (int) count;  -(void)setCount:(int)newCount;

           在实现文件中,@synthesize count; 等价于 - (int) count{ return count; }  - (void) setCount:(int)newCount { count = newCount; } 

     1.3 @property 可以将同类型的实例变量写在一行,不同类型需分开写;@synthesize 则无论类型

     1.4 @property (参数) 类型 名字;

2、参数

     2.1 三类参数:读写属性(readwrite,readonly) setter语意(assign,retain, copy) 原子性(atomic, nonatomic)

     2.2 readwrite 产生setter、getter方法(默认)

readonly 只产生getter方法,没有setter方法

assign 直接赋值,适用于基本数据类型(默认)

retain 旧空间释放再进行retain操作,适用于OC对象

copy 旧空间释放再进行copy操作,适用于NSString等不可变对象(?)

nonatomic 禁止多线程,提高性能

atomic 提供多线程安全,防止在写未完成的时候被另一个线程读取,造成数据错误。如果使用多线程,有时会出现两个线程相互等待对方导致死锁,使用atomic防止出现此情况,但会消耗一定资源。(加锁,解锁)(默认)

     2.3 

<span style="font-size:12px;">//assign
get
- (Toy *) toy;
- (Toy *) toy
{
return toy;
}
set
- (void) setToy:(Toy *)_toy;
- (void) setToy:(Toy *)_toy
{
toy = _toy;
}
//retain
get
- (Toy *) toy;
- (Toy *) toy
{
return toy;
}
set
- (void) setToy:(Toy *)_toy;
- (void) setToy:(Toy *)_toy
{
if (toy != _toy)  //避免自赋值
{
[toy release];  //旧空间释放,引用计数器-1
toy = [_toy retain];  //引用计数器+1,最终指向同一内存空间
}
}
//copy
get
- (Toy *) toy;
- (Toy *) toy
{
return toy;
}
set
- (void) setToy:(Toy *)_toy;
- (void) setToy:(Toy *)_toy
{
if (toy != _toy)
{
[toy release];
toy = [_toy retain];  //复制该内存存储的内容,赋给一个新建的对象,最终指向不同的内存空间,但内容相同
}
}</span>
3、类的组合

     3.1 @class 。。。;  前向声明,提高程序运行效率,需要在.m中再用import导入
     3.2 Has-A为组合关系,Is-A是继承关系
A、属性声明
Toy.h
#import <Foundation/Foundation.h>

@interface Toy : NSObject

@property (nonatomic) int num;
@property (nonatomic, retain) NSString * color;
//- (int) num;
//- (NSString *) color;
//- (void) setNum:(int)_num andColor:(NSString *)_color;
- (void) print;
@endToy.m
#import "Toy.h"

@implementation Toy

@synthesize num, color;
//- (int) num
//{
// return num;
//}
//- (NSString *) color
//{
// return color;
//}
//- (void) setNum:(int)_num andColor:(NSString *)_color
//{
// num = _num;
// color = _color;
//}
- (void) print
{
NSLog(@"num: %d, color: %@", num, color);
}
@endBaby.h
#import <Foundation/Foundation.h>
#import "Toy.h"
@interface Baby : NSObject

@property (nonatomic, retain) Toy * toy;
@property (nonatomic, retain) NSString * name;
@property (nonatomic) int age;
//- (Toy *) toy;
//- (NSString *) name;
//- (int) age;
//- (void) setToy:(Toy *)_toy;
//- (void) setName:(NSString *)_name andAge:(int)_age;
- (void) print; //不声明只实现,就是私有方法,只能在.m中使用
//- (void) dealloc; //系统自动调用,就算不声明只实现,也可以正常使用
@end
////assign
//get
//- (Toy *) toy;
//- (Toy *) toy
//{
// return toy;
//}
//set
//- (void) setToy:(Toy *)_toy;
//- (void) setToy:(Toy *)_toy
//{
// toy = _toy;
//}
////retain
//get
//- (Toy *) toy;
//- (Toy *) toy
//{
// return toy;
//}
//set
//- (void) setToy:(Toy *)_toy;
//- (void) setToy:(Toy *)_toy
//{
// if (toy != _toy)
// {
// [toy release];
// toy = [_toy retain];
// }
//}
////copy
//get
//- (Toy *) toy;
//- (Toy *) toy
//{
// return toy;
//}
//set
//- (void) setToy:(Toy *)_toy;
//- (void) setToy:(Toy *)_toy
//{
// if (toy != _toy)
// {
// [toy release];
// toy = [_toy retain];
// }
//}Baby.m
#import "Baby.h"

@implementation Baby

@synthesize name, age, toy;
//- (Toy *) toy
//{
// return toy;
//}
//- (NSString *) name
//{
// return name;
//}
//- (int) age
//{
// return age;
//}
//- (void) setToy:(Toy *)_toy
//{
// if (toy != _toy)
// {
// [toy release];
// toy = [_toy retain];
// }
//}
//- (void) setName:(NSString *)_name andAge:(int)_age
//{
// name = _name;
// age = _age;
//}
- (void) print
{
NSLog(@"name: %@, age: %d", name, age);
[toy print];
}
- (void) dealloc
{
[toy release];
[super dealloc];
}
@end
main.m
#import <Foundation/Foundation.h>
#import "Baby.h"
int main()
{
@autoreleasepool
{
Baby * b = [[Baby alloc] init]; //初始化的Baby含有指针toy,但为nil,因为没有新建Toy对象并赋值
b.name = @"AAA";
b.age = 5;
b.toy.color = @"紫";
b.toy.num = 5;
[b print];
NSLog(@"num: %d, color: %@", b.toy.num, b.toy.color);

Toy * t1 = [[Toy alloc] init];
t1.num = 10;
t1.color = @"红";
[t1 print];

Toy * t2 = [[Toy alloc] init];
t2.num = 20;
t2.color = @"绿";
[t2 print];

b.toy = t1;
[b print];
b.toy = t2;
[b print];
b.toy.color = @"紫";
b.toy.num = 5;
NSLog(@"num: %d, color: %@", b.toy.num, b.toy.color);

[b release];
[t1 release];
[t2 release];
}
}
B、组合
XYPoint.h
#import <Foundation/Foundation.h>
@class Circle;
@interface XYPoint : NSObject
{
int x;
int y;
}
@property int x, y;
- (void) setX:(int)xVal andY:(int)yVal;
@endXYPoint.m
#import "XYPoint.h"

@implementation XYPoint
@synthesize x, y;
- (void) setX:(int)xVal andY:(int)yVal
{
x = xVal;
y = yVal;
}
@endCircle.h
#import <Foundation/Foundation.h>
//#import "XYPoint.h"
@class XYPoint;
@interface Circle : NSObject
4000
{
int radius;
XYPoint * origin;
}
@property int radius;
- (XYPoint *) origin;
- (void) setOrigin : (XYPoint *)pt;
- (int) area;
- (int) perimeter;
@end
//objective-c中,当一个类使用到另一个类时,并且在类的头文件中需要创建被引用的指针时,如下面代码:
//A.h文件
//#import "B.h"
//@interface A : NSObject {
// B *b;
//}
//@end
//为了简单起见:A类是引用类,B类是被引用类,这里先不考虑A类的实现文件。
//通常引用一个类有两种办法:一种是通过#import方式引入;另一种是通过@class引入;
//这两种的方式的区别在于:
//1、#import方式会包含被引用类的所有信息,包括被引用类的变量和方法;@class方式只是告诉编译器在A.h文件中 B *b 只是类的声明,具体这个类里有什么信息,这里不需要知道,等实现文件中真正要用到时,才会真正去查看B类中信息;
//2、使用@class方式由于只需要被引用类(B类)的名称就可以了,而在实现类由于要用到被引用类中的实体变量和方法,所以需要使用#importl来包含被引用类的头文件;
//3、通过上面2点也很容易知道在编译效率上,如果有上百个头文件都#import了同一 个文件,或者这些文件依次被#improt(A->B, B->C,C->D…),一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍,这样的效率也是可想而知的,而相对来讲,使用@class方式就不会出现这种问题了;
//4、对于循环依赖关系来说,比方A类引用B类,同时B类也引用A类,B类的代码:
//#import "A.h"
//@interface B : NSObject {
// A *a;
//}
//@end
//当程序运行时,编译会报错,
//当使用@class在两个类相互声明,就不会出现编译报错。
//由上可知,@class是放在interface中的,只是在引用一个类,将这个被引用类作为一个类型,在实现文件中,如果需要引用到被引用类的实体变量或者方法时,还需要使用#import方式引入被引用类。Circlr.m
#import "Circle.h"
#import "XYPoint.h"
@implementation Circle
@synthesize radius;
- (XYPoint *) origin
{
return origin;
}
- (void) setOrigin : (XYPoint *)pt
{
origin = pt;
}
- (int) area
{
return 3.14 * radius * radius;
}
- (int) perimeter
{
return 2 * 3.14 * radius;
}
@endmain.m
#import <Foundation/Foundation.h>
#import "Circle.h"
#import "XYPoint.h" //如果不包含会报错,XYPoint是外部定义的类
int main()
{
@autoreleasepool
{
XYPoint * p = [[XYPoint alloc] init];
p.x = 2;
p.y = 2;
Circle * c = [[Circle alloc] init];
c.radius = 2;
NSLog(@"%d",c.radius);
c.origin = p;
NSLog(@"%@",c.origin);
NSLog(@"%d, %d",c.origin.x, c.origin.y);
NSLog(@"%d, %d",[[c origin] x], [[c origin] y]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ObjC课程