2009-11-08 50 views
3

self在C++中不能完全与this互换?self in objective-c

它似乎与消息传递([self sayHi]将工作在任何方法)。

我不明白为什么我不能使用自我访问对象的私有成员(在下面的例子中,我告诉我不能使用self.width)

 
#import <Foundation/Foundation.h> 


// Write an objective-c class 
@interface Rectangle : NSObject 
{ 
    int width ; 
} 

-(int)getWidth; 
-(void)setWidth:(int)w; 
-(void)sayHi; 
-(void)sayHi:(NSString*)msg ; 
@end 

@implementation Rectangle 

-(int)getWidth 
{ 
    // return self.width ; // ILLEGAL, but why?? 
    // why can't I return self.width here? 
    // why does it think that's a "method"? 
    return width ; 
} 
-(void)setWidth:(int)w 
{ 
    // self.width = w ; // ILLEGAL 
    // again here, i CAN'T do self.width = w ; 
    width = w ; 
} 
-(void)sayHi 
{ 
    puts("hi"); 
} 
-(void)sayHi:(NSString*)msg 
{ 
    printf("Hi, and %s\n", [ msg UTF8String ]) ; 
} 

@end 



int main (int argc, const char * argv[]) 
{ 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 


    Rectangle* r = [ Rectangle alloc ] ; 
    [ r sayHi ] ; 
    [ r setWidth:5 ] ; 
    printf("width is %d\n", [ r getWidth ]) ; 


    [pool drain]; 
    return 0; 
} 

回答

12

其他答案几乎是正确的,但并不完全。

在Objective-C中,没有任何对象[保存为块,但这是非常特殊的情况]永远在堆栈中。因此,self.width没有意义。

但是,self->width确实工作。由于self是对堆中分配的结构的有效引用,因此使用->运算符获取成员变量是有意义的。

但是,在Objective-C的情况下,通常也没有意义。也就是说,Objective-C通常假定保留封装的原理。也就是说,你通常不会直接与实例变量(内部状态)进入一个对象和混合体。相反,您使用访问器来获取/设置状态。通过这样做,对象(和子类)可以根据需要自定义getter/setter行为。 (这包括诸如键值观测和键值编码之类的机制)。

self.width碰巧等于[self width][self setWidth: ...something...]是从上面的影响。也就是说,用于访问Objective-C类实例成员的.运算符没有被其他方式使用,并且可能被重载作为属性访问的简写。

但是,属性访问之间几乎没有区别调用getter/setter方法。因此,点符号是方法调用的同义词。


在代码的上下文中,实例变量在您的类实现中是透明可访问的,并且没有前缀。

因此,您通常会使用width = 5.0;而不是self.width = 5.0;。当然,由于上述原因,后者does等同于Objective-C 2.0的方法调用。

5

你可以不要使用self.width,因为它不是一个属性。 self.width = w是在Objective-C 2.0中引入的[self setWidth:w];的简写。尝试在接口文件中的方法原型上方添加@property int width;,并在@implementation行下的实施文件顶部添加@synthesize width;。这应该允许你使用self.width,但它不再是一个私有变量。

你也可以使用@property (readonly) int width;只有为宽度生成一个'getter'方法,但我怀疑这就是你想要的。有关更多选项,您可以传递给@property,请检查this documentation page

另外,像Cliff说的那样,getVar在Objective-C中不是常规。相反,您只需使用您想要公开的变量的名称。就我所知,前缀get通常用于返回某种形式的原始数据。

+0

哦,他真的很...甜。所以点符号只是简单的翻译成方括号内容。谢谢!这个答案有帮助。 – bobobobo

+2

Apple's Cocoa Coding Guidelines(http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingMethods.html#//apple_ref/doc/uid/20001282)声明'get'前缀只能在通过方法参数中指定的指针间接返回多个值时使用。例如,NSColor有一个名为'getRed:blue:green:alpha'的方法,该方法通过给定的'CGFloat'指针返回颜色的RGBA分量。 – hbw

+0

类别。点符号实际上与'@ property'完全正交。实际情况是,Objective-C对象从来不在堆栈中(除了块以外,这是一个非常特殊的情况),因此,访问成员的'.'没有任何意义。 – bbum

4

self.width是[自我宽度]的缩写,既然您没有定义宽度方法,它将是非法的。 ObjC中的获取者并不像其他语言(如Java)那样按照惯例“开始获取”。另外我从其他专家那里听说过(尽管我不明白为什么),从拥有Proerty的对象中使用属性语法并不是一个好主意。从我听到的情况来看,它会导致一些关键值编码问题。在你的例子中,如果你想定义一个自定义的getter/setter,那么只需直接引用该值,而不需要自定义符。在其他地方使用getter/setter或点符号来实现良好的封装可能是有意义的。

2

self in Objective-C,就像this在C++中,是一个指针到当前对象。所以要通过self访问一个字段,你会做self->width(就像在C++中使用this->width一样)