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


Answers:


103

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

类扩展是一个类别,但以下两个主要区别除外:

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

    @interface SomeClass()
    
    
    - (void) anAdditionalMethod;
    
    @结束
  2. 扩展的实现必须在文件的主@implementation块中。

在.m文件的顶部看到一个类扩展在该类上声明更多方法是很常见的,然后在该类的主@implementation部分中实现这些方法。这是一种声明“伪私有”方法的方法(伪私有方法不是真正的私有,只是没有外部公开)。


13
在Class-Extensiosn中,您可以从(公共)只读属性覆盖属性以在内部进行读写。而且从LLVM 1.5开始,您还可以做更多的事情:现在,您可以在类扩展中声明实例变量,以便它们从常规接口中消失。
Max Seelemann

当您只需在类中实现这些方法和属性时,为什么还要添加类扩展?对我来说似乎有点多余。
user1721803 2014年

1
@ user1721803正如Dave所建议的那样,您可能希望保持少量未公开的属性/方法。这是使用扩展名的时候。考虑一个视图,您可以将所有IBOutlets和IBAction扩展连接起来,并公开允许初始化/更新Outlets和Action的方法,这些方法可以委托回来。
2014年

@MaxSeelemann您可以演示如何通过短脚本使“(公共)只读属性在内部进行读写”吗?谢谢。
allenlinli

此答案说明扩展名在“ Class + CategoryName.swift”文件中,是否正确?
Rishi

47
  1. 类别

=>在目标C中,当您想向类添加更多功能而不继承时,只需为其使用类别。

=>它带有自己的.h.m文件

=>Category用于添加新方法而不是属性。

  1. 类扩展
-> In Objective C, when you want to make behaviour of some property private you use class extension.

-> it comes with **.h** file only.

-> mainly for properties.

注意:当我们添加一个新文件并选择一个目标c的选项时,category会显示category和“ category on”而不是“ subclass of”,因此它显示为

@interface className (categoryName)
@end

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

在扩展情况下,您将获得

@interface className()
@end

-您将仅获得一个名为className_extensionName.h的文件

  • 在类别中,您不拥有课程,但在扩展中,您拥有。

5
@Prasanna:类扩展名仅带有.m文件,而不带有.h
Saggy

1
类扩展名仅带有.h文件,而不带有.m
Nishu_Priya,

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

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

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

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

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

  5. 当您必须根据不同的功能将相同的类代码分成不同的源文件时,请使用category;而当您只需要在主接口文件之外的现有类中添加一些必需的方法时,请使用category。另外,当您需要在类中修改一个公共声明的实例变量时,例如,以只读方式进行读写操作,则可以在扩展中重新声明它。


3
我读了5个类似的问题,有很多答案,这是最好的。谢谢!
亲爱的

1
您也可以在类别中添加属性。参见@Pebby答案。
atulkhatri

7

扩展:使方法私有,并添加我们自己的自定义类(而不是Apple类)的属性。

类别:要在现有类(而不是属性)中添加更多方法,则可将其用于自定义类和Apple类NSString


简洁大方。继续努力
阿卜杜勒·亚辛

3

我们还可以在类别类中具有使用set关联属性的属性。

@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/


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


这是您声明和扩展的方式,而不是类别-> @interface SomeClass()
ChavirA

0

与C#,java抽象类相似的ios扩展或
与C#,java类扩展相似的ios类别


4
您的回答就像“猫类似于老虎,回答盲人”。大声笑
Muruganandham K

1
实际上不是。如果您了解c#或java,这是最直接,最快速的解释。
Add080bbA

完全没有描述性,几乎没有回答问题。
KVISH

0

分类目录

创建包含大量方法的文件时使用类别,因此它们为您提供了将单个类分解为不同模块的便利,并且即使对类别进行了任何更改,编译器也不会浪费时间来编译整个项目类别无法添加新的变量或属性并查看其父类。您可以覆盖类别中的方法,但这不是一个好主意,因为该方法无法进一步被覆盖。此外,由于所有类别都有具有相同的层次结构级别,因此在运行时可能存在两个属于同一父类的类别。还可以使用类别创建受保护的方法

扩展名

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

链接提供更多帮助


0

这是我的理解:

扩展通常用于向我们自己的“自定义类”添加其他功能。我们可以添加扩展类接口的私有方法或属性,这些方法或属性可以在类的实现中使用。

扩展名应与该类写入同一文件中。因此,您不能为诸如String,Float等预定义类型编写扩展名。

另一方面,类别可用于向现有类中添加其他方法。例如,我们可以通过扩展String类来创建自己的方法。请注意,我们无法在类别中创建其他属性。类别的另一个主要优点是我们可以将类别写入任何其他文件中,而不是您的类所在的文件。

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


你有点偏离轨道。
阿卜杜勒·雅辛18'Mar

@iPhoneDeveloper我们可以为预定义类型编写扩展名。请检查此链接- stackoverflow.com/a/33942484/2060508
yo2bh
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.