【问题标题】:Why do I have to use self. to reference own object为什么我必须使用 self.引用自己的对象
【发布时间】:2013-04-04 14:36:11
【问题描述】:

我正在通过斯坦福大学的 iTunesU 计划学习 iOS 开发。我遇到了一个意想不到的问题。

我添加了一个 clear 方法,但是我收到了这个错误 //使用未声明的标识符'operandStack';你的意思是'_operandStack'吗?

我知道我可以通过使用 [self.operandStack ...etc 而不是 [operandStack

来解决问题

为什么我需要自我?不是暗示了吗?为什么我在引用_operandStack时不需要使用self?

#import "CalculatorBrain.h"

@interface CalculatorBrain()
//string because we are the only ones interested
@property  (nonatomic, strong) NSMutableArray *operandStack;
@end



@implementation CalculatorBrain

@synthesize operandStack = _operandStack;

- (void) setOperandStack:(NSMutableArray *)operandStack
{
    _operandStack = operandStack;
}

- (NSMutableArray *) operandStack
{
    if(_operandStack==nil) _operandStack = [[NSMutableArray alloc] init];
    return _operandStack;
}

- (void) pushOperand:(double)operand
{
    NSNumber *operandObject = [NSNumber numberWithDouble:operand];


    [self.operandStack addObject:operandObject];

}

- (double) popOperand
{
    NSNumber *operandObject = [self.operandStack lastObject];

    if (operandObject !=nil)
    {
        [self.operandStack removeLastObject];
    }
    return [operandObject doubleValue];
}

- (void) clear
{
    //clear everything
    [operandStack removeAllObjects];

//***************************强> //使用未声明的标识符'operandStack';你的意思是“_operandStack”吗?

}

- (double) performOperation:(NSString *)operation
{
    double result =0;
    //calculate result
    if ([operation isEqualToString:@"+"]) {
        result = [self popOperand] + [self popOperand];
    } else if ([operation isEqualToString:@"*"]) {
        result = [self popOperand] * [self popOperand];
    } else if ([operation isEqualToString:@"π"]) {
        [self pushOperand:3.14159];
        NSNumber *operandObject = [self.operandStack lastObject];
        return [operandObject doubleValue];
    }
    [self pushOperand:result];
    return result;
}
@end

【问题讨论】:

  • 在继续之前再次观看课程。他们对此非常清楚,您应该掌握 setter/getter 与实例变量的概念,并熟悉在整个课程中一直使用的惰性实例化。
  • 延迟实例化很容易。我非常了解 getter 和 setter 以及实例变量。我的理解是,在引用实例方法或属性时我们需要使用 self,而我们不需要将 self 用于 _operandStack。在我的 C#/.NET 背景中, this 总是引用当前实例,并且可用于访问实例中可访问的任何对象。

标签: ios objective-c


【解决方案1】:

因为你已经合成了它(注意:在较新的 Objective-C 版本中合成是自动的):

@synthesize operandStack = _operandStack;

这意味着您生成了getter 和setter,并且您通过调用_operandStack 来访问该属性。如果你想把它叫做operantStack,把它改成这样:

@synthesize operandStack;

如果您使用 self.operandStack,则您使用的是属性生成的 getter/setter,而不是合成的。

使用合成属性和非合成属性是不同的,没有像许多人认为的那样访问属性的“推荐方式”,它们只是具有不同的含义。例如这里:

- (void) setOperandStack:(NSMutableArray *)operandStack
{
    _operandStack = operandStack;
}

您必须使用综合属性,否则您将进入无限循环。合成属性是自动生成的,非合成属性也是自动生成的,但它可以被覆盖,就像你在那种情况下所做的那样,它也可以在外部访问。

【讨论】:

  • 我即将给出这个答案:) +1。
  • 可能需要稍微澄清一下。 _operandStack(或“@synthesize operandStack”时的operandStack)不是访问器而是实例变量。所以前缀与否的区别就是调用getter和直接访问实例变量的区别。
  • _operandStack 是对 ivar 的直接引用(在上面的示例中)。 @synthesize(通常)创建两个访问器:-(void)setOperandStack:(NSMutableArray *)-(NSMuableArray *)operandStackself.operandStack 的使用将使用适当的访问器,具体取决于它是位于赋值操作的左侧 (LHS) 还是 RHS。因为已经合成的访问器是隐式实现的,所以将使用隐式版本。 synthesize 方法确实会导致它创建一个隐式 ivar 名称 _operandStack。
  • 如果使用 ARC(自动引用计数),应该没有问题。如果没有,setOperandStack: 将无法正确保留引用。根据类的使用方式,这个问题可能会出现,也可能不会出现。
  • 为什么不一样呢?例如,_operandStack、setOperandStack 和operandStack(属性)都存在于实例上。为什么我们对实例上的方法和属性使用self,但是在引用_operandStack时不需要包含self。 _operandStack 存在于同一个实例中。所以我正在寻找的答案是关于可访问性我猜。可公开访问的实例成员需要 self?而其他人没有?在我的 .NET 背景中,实例中的任何内容都可以通过类似于 self 的“this”访问。
猜你喜欢
  • 1970-01-01
  • 2017-02-24
  • 1970-01-01
  • 2022-06-15
  • 1970-01-01
  • 2016-10-17
  • 1970-01-01
  • 2015-03-09
  • 1970-01-01
相关资源
最近更新 更多