简体   繁体   English

为什么我们可以在方法的实现中使用自定义/基础类的实例而无需先对该实例进行alloc和init?

[英]Why can we use an instance of a custom/foundation class in the implementation of a method without first doing alloc and init for the instance?

This question is based on the code from the first lecture in the Stanford iOS series 2014 (objective - c). 该问题基于2014年Stanford iOS系列(目标-c)的第一次演讲的代码。

We created a class called Card which includes a method named match: which will be used to determine how different cards will match up against one another in the game, and this method takes as an argument an NSArray called *otherCards and we use an instance of Card called *card to iterate through this array in the implementation of this method. 我们创建了一个名为Card的类,其中包含一个名为match:的方法,该方法将用于确定游戏中不同纸牌之间的匹配方式,该方法将一个名为*otherCardsNSArray作为参数,并且使用在此方法的实现中,名为*card Card可以迭代此数组。

My question is this - how can we just declare an instance of our class Card ie *card and use it as an iterating variable in the for loop without first allocating and instantiating it? 我的问题是-我们如何仅声明Card类(即*card的实例并将其用作for循环中的迭代变量,而无需首先分配和实例化它? In the same vein, how can we just declare *otherCards as an instance of NSArray and then use it in the cycling through of the for loop before it is allocated and initialised also? 同样,我们如何才能将* otherCards声明为NSArray的实例,然后再在for循环中使用它,然后再对其进行分配和初始化?

I realise this might be done later in the code, but why isn't the compiler throwing at least a warning about this? 我意识到这可能会在代码的稍后部分完成,但是为什么编译器不对此至少抛出警告?

Here is the code: 这是代码:

//Card.h

@interface Card : NSObject

@property (strong, nonatomic) NSString *contents; 
@property (nonatomic, getter=isChosen) BOOL chosen;
@property (nonatomic, getter=isMatched) BOOL matched;

- (int)match:(NSArray *)otherCards;



    //Card.m

  #import "Card.h"

    @implementation Card
    - (int)match:(NSArray *)otherCards
    {


        int score = 0; 
    for (Card *card in otherCards) { 
    if ([card.contents isEqualToString:self.contents ])
    {
            score = 1;
        }

        }

        return score;
    }


    @end

I think your question is about this loop: 我认为您的问题与以下循环有关:

for (Card *card in otherCards) {
    ...
}

how can we just declare *otherCards as an instance of NSArray and then use it 我们如何只将* otherCards声明为NSArray的实例,然后使用它

You don't need to alloc and init otherCards because it is supplied as a parameter to the function match . 您不需要分配和初始化otherCards因为它是作为match参数的参数提供的。 The caller is responsible for initializing it. 调用方负责对其进行初始化。 You can't dodge initialization, just that it's done elsewhere: 您不能躲避初始化,只不过它在其他地方已经完成:

Card * myCard = ...               // init the varible here
NSArray * otherCards = ...        // init the array here
int n = [myCard match:otherCards] // otherCards is now initialized. Don't need to 
                                  // do it again inside your method

how can we just declare an instance of our class Card ie *card and use it as an iterating variable in the for loop 我们如何只声明类Card的实例,即*card并将其用作for循环中的迭代变量

card is not a new object. card不是新对象。 It just points existing objects inside the otherCards array, hence no need to alloc and init. 它仅指向otherCards数组中的现有对象,因此无需分配和初始化。

You did declare card as a pointer of type Card in the for loop: for (Card * card in otherCards) . 您确实在for循环中将card声明为Card类型的指针: for (Card * card in otherCards) This is a syntactic sugar to make code more concise. 这是使代码更简洁的语法糖。 You can do it the long way if you want: 如果需要,可以做很多事情:

Card * card;
for (card in otherCards) {
    // do something
}

…(NSArray *)otherCards and Card *card in are both placeholders. …(NSArray *)otherCardsCard *card in都是占位符。

otherCards is a parameter name. otherCards是参数名称。 The method match expects an (initialized) NSArray as parameter to process the array locally in the method. 该方法match期望一个(初始化的)NSArray作为参数来在方法中本地处理该数组。 The associated pointer (NSArray *) holds the reference to the array until the method is left. 关联的指针(NSArray *)保留对数组的引用,直到离开该方法为止。

Card *card in is a temporary index pointer which holds the reference to one (initialized) item of the array per iteration Card *card in是一个临时索引指针,该指针在每次迭代中保留对数组一个(初始化)项的引用

The instances do exist; 实例确实存在; these are just the local names that you're using for them. 这些只是您使用的本地名称。 You're right that nothing would happen if they hadn't been created first, but it's not this method's job to create them. 没错,如果没有先创建它们就不会发生任何事情,但是创建它们不是这种方法的工作。

There is no compiler warning because you've done nothing wrong at compile time: you've taken an object of type NSArray and iterated through it (using the for( ... in theArray ) syntax), with a temporary name for each of its members. 没有编译器警告,因为您在编译时没有做错任何事情:您已经获取了NSArray类型的对象并对其进行了迭代(使用for( ... in theArray )语法),每个对象都有一个临时名称。它的成员。 It's possible for that array to not exist (be nil ) at runtime, but there's no way for the ObjC compiler to know that; 该数组在运行时可能不存在(为nil ),但是ObjC编译器无法知道这一点; and even if it happened, the result would simply be nothing, not an error. 即使发生了,结果也只会是一无所有,而不是一个错误。

Later code using this method will look something like this: 稍后使用此方法的代码将如下所示:

Card * aCard = [[Card alloc] init];
// set aCard's properties
NSArray * cards = @[anotherCard, aThirdCard, stillAnotherCard];
[card match:cards];

Where all these objects are created and then passed in to the method as needed. 创建所有这些对象,然后根据需要将其传递到方法中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM