类别和类扩展之间的区别?

时间:2010-08-17 06:02:11

标签: objective-c

类别和类扩展之间有什么区别。我相信它们都用于在现有类中添加自定义方法。有人可以对此有所了解吗?我们非常感谢您对代码的示例。

10 个答案:

答案 0 :(得分:98)

类别是一种向现有类添加方法的方法。它们通常驻留在名为“Class + CategoryName.h”的文件中,如“NSView + CustomAdditions.h”(当然还有.m)。

类扩展是一个类别,除了两个主要区别:

  1. 该类别没有名称。声明如下:

    @interface SomeClass ()
    
    
    - (void) anAdditionalMethod;
    
    @end
  2. 扩展程序的实现必须位于文件的主@implementation块中。

  3. 在.m文件的顶部看到一个类扩展,在类上声明更多方法,然后在类的主@implementation部分实现,这是很常见的。这是一种声明“伪私有”方法的方法(伪私有方式,因为它们不是真正的私有,只是没有外部暴露)。

答案 1 :(得分:43)

  1. <强>分类

    =&GT;在Objective C中,当您想要为没有继承的类添加更多功能时,您只需使用类别。

    =&GT;它带有自己的 .h .m 文件

    =&GT; Category用于添加新方法而非属性。

  2. 课程扩展

    - &GT;在Objective C中,当您想要将某些属性的行为设为私有时,您可以使用类扩展。

    - &GT;它仅附带 .m 文件。

    - &GT;主要用于物业。

  3.   

    注意:当我们添加新文件并选择目标c的选项时   它显示类别和&#34;类别&#34;不是&#34;&#34;的子类所以   显示像

    @interface className (categoryName)
    @end
    

    - 您将获得两个文件 .h .m ,文件名为( className + categoryName.h className + categoryName.m

    在扩展案例中,您将获得

    @interface className()
    @end
    

    - 您只会获得一个名称为 className_extensionName.h

    的文件
    • 在类别中,您不拥有该课程,但在扩展中您是。

答案 2 :(得分:30)

  1. 类别是一种向类添加方法的方法,无论源代码是否可用,这意味着您可以将类别添加到基础类(如NSString)以及您自己的自定义类。

    扩展只能添加到源代码可用的类中,因为编译器会同时编译源代码和扩展。

  2. 我们可以在类扩展中添加额外的实例变量和属性,但不能在类别中添加。

  3. 扩展内的任何变量和方法都不能被继承的类访问。

  4. 类别和扩展都基本上用于处理大型代码库,但类别是一种在多个源文件中扩展类API的方法,而扩展是一种在主接口文件之外添加所需方法的方法。

  5. 当您需要根据不同的功能将相同的类代码分成不同的源文件时使用类别,以及当您只需要在主接口文件外部的现有类中添加一些必需的方法时使用扩展。 此外,当您需要修改类中公开声明的实例变量时,例如, readonly to readwrite,你可以在扩展名中重新声明它。

答案 3 :(得分:3)

我们还可以使用属性在类别类中使用set associated属性。

@interface SomeClass (Private)

@property (nonatomic, assign) id newProperty;

@end

NSString * const kNewPropertyKey = @"kNewPropertyKey";

@implementation SomeClass (Private)

@dynamic newProperty;

- (void)setNewProperty:(id)aObject
{
    objc_setAssociatedObject(self, kNewPropertyKey, aObject, OBJC_ASSOCIATION_ASSIGN);
}

- (id)newProperty
{
    return objc_getAssociatedObject(self, kNewPropertyKey);
}

@end

参考:http://inchoo.net/dev-talk/ios-development/how-to-add-a-property-via-class-category/

答案 4 :(得分:2)

@interface SomeClass ()


- (void) anAdditionalMethod;


@end

我认为这不是申报类别的方法。 类别必须具有名称

@interface SomeClass (XYZ)


- (void) anAdditionalMethod;


@end

例如

@interface NSMutableArray (NSMutableArrayCreation)

+ (id)arrayWithCapacity:(NSUInteger)numItems;
- (id)initWithCapacity:(NSUInteger)numItems;

@end

由Apple宣布为NSMutableArray

答案 5 :(得分:2)

扩展程序:将方法设为私有,并添加我们自己的自定义类的属性,而不是Apple类。

类别:要在现有类中添加更多方法而不是属性,它可以用于自定义类和Apple类,如NSString

答案 6 :(得分:1)

ios扩展类似于c#,java抽象类或接口
ios类别与c#类似,java类扩展

答案 7 :(得分:0)

分类

当您创建包含大量方法的文件时使用类别。因此,它们为您提供了将单个类分解为不同模块的功能。如果对类别进行任何更改,编译器也不会浪费时间编译整个project.Categories无法添加新的变量或属性,并查找其父类。您可以覆盖类别中的方法,但它不是一个好主意,因为该方法无法进一步被覆盖。此外,流程可以实现,因为所有类别具有相同的层次级别,因此在运行时可能存在属于同一父类的两个类别。也可以使用类别创建受保护的方法

扩展

Extensions使您可以覆盖属性或向现有父类添加新属性。与它们没有名称的类别相同,并表示为@interface class() 不存在.m文件,扩展中声明的方法必须在父文件的@implementation中实现

this链接提供更多帮助

答案 8 :(得分:0)

以下是我的理解:

扩展程序通常用于为我们自己的&#34; 自定义类&#34;添加额外的功能。我们可以添加扩展类接口的私有方法或属性,可以在类的实现中使用。

扩展名应与该类在同一文件中写入。因此,您无法为预定义类型(如String,Float等)编写扩展名。

另一方面,类别可用于向现有类添加额外方法。我们可以通过扩展String类来创建自己的方法。请注意,我们无法在类别中创建额外的属性。类别的主要优点是我们可以在您的类退出的文件之外的任何其他文件中编写类别。

同样在创建类别时,您应该在括号内为其命名。 但是对于扩展,不需要名称。因此有时它们也被称为匿名类别。

答案 9 :(得分:0)

类别和扩展

类别允许您向现有类添加方法,即使是您没有源的类。类别是一项强大的功能,它允许您扩展现有类的功能而无需子类化。使用类别,您还可以在多个文件中分发您自己的类的实现。类扩展是类似的,但允许在主类 @interface 块之外的位置为类声明额外的必需 API。

向类添加方法

您可以通过在接口文件中以类别名称声明方法并在同名实现文件中定义它们来向类添加方法。类别名称表明这些方法是对在别处声明的类的添加,而不是新类。但是,您不能使用类别向类添加其他实例变量。

类别添加的方法成为类类型的一部分。例如,添加到类别中的 NSArray 类的方法被包含为编译器期望 NSArray 实例在其库中具有的方法。但是,添加到子类中的 NSArray 类的方法不包含在 NSArray 类型中。 (这只对静态类型对象很重要,因为静态类型是编译器知道对象类的唯一方式。)

类别方法可以做任何在类中定义的方法可以做的事情。在运行时,没有区别。类别添加到类中的方法会被该类的所有子类继承,就像其他方法一样。

类别接口的声明看起来很像类接口声明——除了类别名称列在类名称后面的括号内,并且没有提到超类。除非它的方法不访问类的任何实例变量,否则类别必须为它扩展的类导入接口文件:

#import "ClassName.h"
 
@interface ClassName ( CategoryName )
// method declarations
@end

注意,类别不能为类声明额外的实例变量;它只包括方法。但是,类范围内的所有实例变量也在类范围内。这包括类声明的所有实例变量,甚至是声明为 @private 的实例变量。

可以添加到类中的类别数量没有限制,但每个类别名称必须不同,并且每个类别都应该声明和定义不同的方法集。

扩展

类扩展类似于匿名类别,除了它们声明的方法必须在相应类的主 @implementation 块中实现。使用 Clang/LLVM 2.0 编译器,您还可以在类扩展中声明属性和实例变量。

类扩展的一个常见用途是将公开声明为只读的属性重新声明为 readwrite:

@interface MyClass : NSObject
@property (retain, readonly) float value;
@end
 
// Private extension, typically hidden in the main implementation file.
@interface MyClass ()
@property (retain, readwrite) float value;
@end

// Notice that (in contrast to a category) no name is given in the parentheses in the second @interface block.

一个类通常有一个公开声明的 API,然后有其他方法私下声明,仅供该类或该类所在的框架使用。类扩展允许您在主类 @interface 块以外的位置为类声明额外的必需方法,如下例所示:

@interface MyClass : NSObject
- (float)value;
@end
 
 
@interface MyClass () {
    float value;
}
- (void)setValue:(float)newValue;
@end
 
@implementation MyClass
 
- (float)value {
    return value;
}
 
- (void)setValue:(float)newValue {
    value = newValue;
}
 
@end

setValue: 方法的实现必须出现在该类的主 @implementation 块中(您不能在类别中实现它)。如果不是这种情况,编译器会发出警告,提示它找不到 setValue: 的方法定义。 有关官方文档,请点击此链接:source