//
// Student.h
// copy语法2
//
// Created by XinYou on 15-1-27.
// Copyright (c) 2015年 vxinyou. All rights reserved.
//
#import
@interface Student : NSObject
// copy代表name属性的set方法会release旧对象、copy新对象
// 修改外面的变量,并不会影响到内部的成员变量
// 建议:NSString一般用copy策略,其他对象一般用retain策略
@property (nonatomic, copy) NSString *name;
+ (id)studentWithName:(NSString *)name;
@end
//
// Student.m
// copy语法2
//
// Created by XinYou on 15-1-27.
// Copyright (c) 2015年 vxinyou. All rights reserved.
//
#import "Student.h"
@implementation Student
+ (id)studentWithName:(NSString *)name{
// 这里为什么要写成[self class],而不是Student?
// 因为如果Student有一个子类GoodStudent,这里的[self class]就表示GoodStudent
// 这样我们在子类中调用studentWithName的时候得到的就是子类对象,如果得到的是父类对象,程序会出错
Student *stu = [[[[self class] alloc] init] autorelease];
stu.name = name;
return stu;
}
#pragma mark copying协议的方法
- (id)copyWithZone:(NSZone *)zone{
// 这里创建的副本对象不要求释放。这是为什么呢?
// 因为我们在其他的地方对Student对象进行copy操作时,得到的就是这个copyStu对象
// 应该在copy操作之后再对copyStu进行release操作。
// 如果在这里就对copyStu进行release操作,那么在其他地方得到的copyStu对象是已经被释放的对象。
Student *copyStu = [[[self class] allocWithZone:zone] init];
copyStu.name = self.name;
return copyStu;
}
- (NSString *)description{
// 特别注意:不能在description方法内部打印self,不然会造成死循环!!!
// return [NSString stringWithFormat:@"Student = %@", self];
return [NSString stringWithFormat:@"[name = %@]", _name];
}
- (void)dealloc{
[_name release];
[super dealloc];
}
@end
//
// GoodStudent.h
// copy语法2
//
// Created by XinYou on 15-1-27.
// Copyright (c) 2015年 vxinyou. All rights reserved.
//
#import "Student.h"
@interface GoodStudent : Student
@property (nonatomic, assign) int age;
+ (id)goodStudentWithAge:(int)age name:(NSString *)name;
@end
//
// GoodStudent.m
// copy语法2
//
// Created by XinYou on 15-1-27.
// Copyright (c) 2015年 vxinyou. All rights reserved.
//
#import "GoodStudent.h"
@implementation GoodStudent
+ (id)goodStudentWithAge:(int)age name:(NSString *)name{
GoodStudent *goodStu = [GoodStudent studentWithName:name];
goodStu.age = age;
return goodStu;
}
- (id)copyWithZone:(NSZone *)zone{
// 一定要调用父类的方法
GoodStudent *copyStu = [super copyWithZone:zone];
copyStu.age = self.age;
return copyStu;
}
@end
//
// main.m
// copy语法2
//
// Created by XinYou on 15-1-27.
// Copyright (c) 2015年 vxinyou. All rights reserved.
//
#import
#import "Student.h"
#import "GoodStudent.h"
#pragma mark Student对象的name属性的copy
void studentNameCopy(){
Student *stu = [Student studentWithName:@"zhangsan"];
NSMutableString *str = [NSMutableString stringWithString:@"lisi"];
/**
Student中name属性的set方法:
- (void)setName:(NSString *)name{
if (_name != name){
// 先释放旧的
[_name release];
// 再把新的赋值给_name
_name = [name copy];// _name = [name retain];
}
}
*/
// 因为Student的name属性采用的是copy策略,所以name属性的set方法如上所示
// 当执行下面这句代码的时候:
// 会对str这个字符串进行copy操作,产生一个副本(深拷贝),然后把这个副本(内存地址值)赋值给_name
// 然后_name这个指针变量指向了@"lisi"这个字符串
// 然后对str这个可变字符串进行appendString操作,改变的是str,并没有改变str的副本
// 也就是说_name指向的字符串并没有发生改变
// 如果Student的name属性采用的是retain策略,那么当执行下面这句代码的时候:
// 会把str中存储的(内存地址)值赋值给_name,也就是说_name和str指向同一个字符串。
// 然后对str这个可变字符串进行appendString操作,而_name的指向并没有发生改变
// 也就相当于_name这个字符串也进行了appendString操作
stu.name = str;
[str appendString:@"wangwu"];
NSLog(@"stu name is %@", stu.name);// stu name is lisi
NSLog(@"str is %@", str);// str is lisiwangwu
}
#pragma mark Student对象的copy
void studentCopy(){
Student *stu = [Student studentWithName:@"zhangsan"];
Student *stu2 = [stu copy];
stu2.name = @"lisi";
NSLog(@"stu name is %@", stu.name);// stu name is zhangsan
[stu2 release];
}
#pragma mark Student子类对象的copy
void goodStudentCopy(){
GoodStudent *goodStu = [GoodStudent goodStudentWithAge:24 name:@"zhangsan"];
GoodStudent *goodStu2 = [goodStu copy];
goodStu2.name = @"lisi";
goodStu2.age = 34;
NSLog(@"goodStu name is %@", goodStu.name);// goodStu name is zhangsan
NSLog(@"goodStu age is %i", goodStu.age);// goodStu age is 24
[goodStu2 release];
}
int main(int argc, const char * argv[])
{
@autoreleasepool {
// studentNameCopy();
studentCopy();
// goodStudentCopy();
}
return 0;
}
OC基础——copy语法(Student属性的copy、Student对象的copy、Student子类对象的copy)
最新推荐文章于 2022-12-30 15:59:07 发布