【使用分类的注意细节 Objective-C语言】

前言

使用分类需要注意四个细节:

一、分类只能增加方法,不能增加属性

例如,有下面一个分类,这么写是错误的:
@interface Person (test)
{
int _age;
}
– (void)haha;
@end
这句话会报错:int _age;
意思是,分类不能写属性!

二、在分类之中可以写@property ,但是不会自动生成私有属性,也不会自动生成getter、setter的实现,只会生成getter、setter的声明。

例如,如下这种写法:
@interface Person (test)
@property(nonatomic,assign)int age;
– (void)haha;
@end
不会生成_age私有属性,也不会生成- (void)setAge方法,和- (int)age方法。
如果编译以下的语句,会报发送给实例的消息无法识别,哪个消息呢,[Student setAge:]消息:
int main()
{
Student *s1 = [Student new];
[s1 setAge:19];//这句话会报错
return 0;
}
怎么办呢,如果你就是想在分类中使用@property声明属性呢,自己在分类的实现文件里写setter、getter方法呗。但是如下写法是错误的:
@interface Student (test)
{
int _age;
}
– (void)setAge:(int)age
{
_age = age;
}
– (int)age
{
return _age;
}
因为我们刚刚说过,在分类中是不能增加属性的,只能增加方法。
那怎么办呢,你在Student.h文件中写一个int _age;属性是可以的。
那为什么你在Student.h里写的属性,在Student+test.m文件里能访问呢,因为是同一个类。
我记得我们之前讲过,@synthesize可以自动生成私有属性,还可以自动生成setter、getter方法的实现,那在分类的实现文件里写一个这句话,可不可以呢?
@synthesize age = _age;
也不行,还是报错:
@synthesize not allowed in a category’s implementation
所以,总结:
在分类之中可以写@property , 但是不会自动生成私有属性,也不会自动生成getter、setter方法的实现,只会生成getter、setter方法的声明。
所以,你就需要自己写getter、setter的实现,也需要自己定义属性。这个属性,就必须在本类的.h文件当中。

三、在分类的方法实现当中,不可以直接访问本类的私有属性。但是可以调用本类的getter、setter方法来访问属性。

例如,这里指的私有属性,不是定义在本类的.h文件中的标记有@private的属性:
@interface Student : NSObject
{
@private
int _age;
}
@end
这个_age属性,在分类的.m文件里是可以访问的,例如:
@implementation Student (test)
– (void)sayHi
{
_age = 19;
}
@end
但是,这个定义在本类.m文件中的真私有属性,就访问不了了:
@implementation Student
{
NSString *_name;
}
@end

@implementation Student (test)
– (void)sayHi
{
_name = @“jack”;
}
@end
这样就不行了。。。
在分类的方法实现中不可以直接访问本类的真私有属性(定义在本类的@implementation之中的属性),但是可以调用本类的getter、setter方法来间接访问属性
例如:
@interface Student:NSObject
@property(nonatomic,strong)NSString *name;
@end
这个@property生成的私有属性,是真私有属性,这个_name在分类里面仍然是无法访问的,但是虽然无法直接访问私有属性,但是可以通过点语法,即是调用setter、getter方法间接访问这个私有属性。
@implementation Student (test)
– (void)sayHi
{
self.name = @“jack”;
}
@end
本类的@property生成的私有属性,只可以在本类的实现中访问,
分类中不能直接访问私有属性 真私有属性。
分类可以使用getter、setter 来访问
例如:[self setName:@“jack”];
这样是可以的

四、分类中可以存在和本类同名的方法的 ,当分类中有和本类中同名的方法的时候,优先调用分类的方法,哪怕没有引入分类的头文件,如果多个分类中有相同的方法,优先调用最后编译的分类。在Target编译选项里,Build Phases里的Compile Sources里,可以调整编译顺序,分类中哪1个在下面,哪一个后编译,调用的就是哪1个分类里面的sayHi方法,例如:

#import

@interface Student : NSObject
{
@private
int _age;
}

  • (void)haha;
    @property(nonatomic,strong)NSString *name;
  • (void)sayHi;
    @end
    #import “Student.h”

@implementation Student

  • (void)haha
    {
    NSLog(@“哈哈。。。”);
    }
  • (void)sayHi
    {
    NSLog(@“我是本类的sayHi方法。。。”);
    }
    @end

#import “Student.h”

@interface Student (test)
@property(nonatomic,assign)int age;

  • (void)hehe;
  • (void)sayHi;
    @end
    #import “Student+itcast.h”

@implementation Student (test)

  • (void)setAge:(int)age
    {
    _age = age;
    }
  • (int)age
    {
    return _age;
    }
  • (void)sayHi
    {
    self.name = @“jack”;
    _age = 19;
    NSLog(@“我是分类test的sayHi方法。。。”);
    }
  • (void)hehe
    {
    NSLog(@“呵呵。。。”);

}
@end
#import “Student.h”

@interface Student (test2)

  • (void)test2;
  • (void)sayHi;
    @end
    #import “Student+sb.h”

@implementation Student (test2)

  • (void)test2
    {
    NSLog(@“嘿嘿。。。”);
    }
  • (void)sayHi
    {
    NSLog(@“我是分类test2中的sayHi方法。。。”);
    }
    @end

五、举个例子,说一下上面的第三点:

例如,有一个Person类,有一个真私有属性,int _age;
#import
@interface Person:NSObject
– (void)setAge:(int)age;
– (void)age;
@end
#import “Person.h”
@implementaion Person
{
int _age;
}
– (void)setAge:(int)age
{
_age = age;
}
– (void)age;
{
return _age;
}
@end
//为Person类来一个分类:
#import “Person.h”
@interface Person (test)
– (void)tt;
@end
#import “Person+test.h”
@implementation Person (test)
– (void)tt
{
self->_age;//这句话会报错,Person类没有_age属性
}
@end

1、所以,本类中的真私有属性在分类中无法直接访问,指的是声明在本类的@implementation当中的属性,如果是声明在本类的@interface当中的属性,分类可不可以访问,可以。

2、但是,可以通过本类的setAge方法和age方法,访问真私有属性_age;

#import “Person.h”
@interface Person (test)
– (void)tt;
@end
#import “Person+test.h”
@implementation Person (test)
– (void)tt
{
[self setAge:19];//这样是可以的
int age = [self age];//这样也是可以的。
}
@end

你可能感兴趣的:(Objective-C,objective-c,开发语言,macos)