关于xcode:Objective C:类方法说明

Objective C: Class Method Explanation

作为我从C++到Objto-C的过渡过程的一部分,我深入阅读了CoCa和ObjeC+UP并运行。

在其中一本书的代码示例中,有一行对我当前的知识水平没有意义:

它是类方法+ (Photo*) photo;的声明。

有人能解释一下为什么作者决定让(Photo*) photo;方法声明为类方法而不是实例方法吗?

我已经研究了这个理论,Stand方法类似于类成员函数,类方法类似C++中的静态函数。但这仍然不能回答我的问题。

这是申报代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#import <Foundation/Foundation.h>


@interface Photo : NSObject{

    NSString* caption;
    NSString* photographer;    
}

+ (Photo*) photo;

- (NSString*) caption;
- (NSString*) photographer;

- (void) setCaption: (NSString*)input;
- (void) setPhotographer: (NSString*)input;

@end

实施代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#import"Photo.h"


@implementation Photo

- (id)init
{
    self = [super init];
    if (self) {
        [self setCaption:@"Default Caption"];
        [self setPhotographer:@"Default Photographer"];
    }

    return self;
}


+ (Photo*) photo {
    Photo* newPhoto = [[Photo alloc] init];
    return [newPhoto autorelease];
}


- (NSString*) caption {
    return caption;
}


- (NSString*) photographer {
    return photographer;
}


- (void) setCaption:(NSString *)input {
    [caption autorelease];
    caption = [input retain];
}


- (void) setPhotographer: (NSString *)input {
    [photographer autorelease];
    photographer = [input retain];
}


- (void)dealloc
{
    [self setCaption:nil];
    [self setPhotographer:nil];

    [super dealloc];
}

@end


+ (Photo*) photo方法是一种工厂方法,它封装了创建photo类对象的详细信息。

A Factory Method enforces
encapsulation, and allows an object to
be requested without inextricable
coupling to the act of creation.

在这个特定的示例中,工厂方法隐藏的信息是内存管理,因为客户机不需要担心释放返回的对象。

在Objective-C API中,在返回同一类的自动释放对象的类中提供工厂方法是一种常见的实践。这些方法不能包含任何单词"alloc"、"new"、"copy"或"mutablecopy",根据约定,这些单词表示调用方不拥有返回的对象,即不必显式释放它。

相关资源:

  • 内存管理规则


元回答:

One issue; that method should be
declared as returning id and should
return [[[self alloc] init]
autorelease]; (one line or two,
doesn't matter -- just should refer to
the Class directly). As it is, Photo
is gonna be a pain to subclass.

扩展——鉴于此:

1
2
3
4
+ (Photo*) photo {
    Photo* newPhoto = [[Photo alloc] init];
    return [newPhoto autorelease];
}

如果该类是子类的,那么如果不重写该工厂方法来执行几乎相同的操作,它将无法工作。但是,由于objective-c不支持共方差和反向方差,因此无法声明子类的EDOCX1[0]实现以返回子类的实例,而不会同时运行编译器警告的重大风险。或者,您可以将返回值向下强制转换为更具体的类,但这充满了脆弱性。

相反,请执行以下操作:

1
2
3
4
+ (id) photo {
    id newPhoto = [[self alloc] init];
    return [newPhoto autorelease];
}

这解决了两个问题:

  • 因为它使用self,它将实例化在其上实现的任何类的实例,包括photo的子类。

  • 由于它返回id,调用者可以不经发行就执行以下两种操作:

    photo*p=[照片];subclasssofphoto*s=[subclasssofphoto照片];


在这个场景中,photo是一个方便的方法,它返回类的autoreleased实例。

因为photo的目的是给你一个实例,所以把它变成一个实例方法是没有意义的,因为它要求你已经有了一个实例。

如果你熟悉工厂的方法,照片的方法与之类似。


如您所说,它等价于静态方法。在这种情况下(以及所有的[ClassName className]方法),它基本上是一种工厂方法。您要求类构造自己的实例并将其传递回。所有这些方法都应该返回一个自动释放的对象。

如果您愿意,可以安全地忽略这样的方法-通常会有一个alloc+init等价物,但是使用类方法通常更方便,特别是在您创建一个thraway对象并且不想保留它的情况下。

最后,您有时会发现需要使用class方法的类,因为它们会隐藏一些聪明的逻辑,其中实际返回了另一个类的实例。你有时会听到这些被描述为"类集群"。


+photo就像一个构造函数。您需要一种方法来获取要将实例方法发送到的对象,这将为您提供一个自动释放的方法。


Could anybody explain me the reason, please, why the author had decided for the method (Photo*) photo; to declare it as a class method instead of instance method?

它基本上是构造函数列表的包装。注意来源:

1
2
3
4
+ (Photo*) photo {
    Photo* newPhoto = [[Photo alloc] init];
    return [newPhoto autorelease];
}

分配一张新照片,初始化它,标记它自动释放,然后返回它。因为它创建了对象,所以还没有对象可以操作,因此这需要是一个类方法。