Почему мой объект суперкласса вызывает метод своего подкласса?

Я видел здесь много полезных тем, но пишу впервые!

Я работал над печально известным проектом Stanford OpenCourse: Matchismo. Пока у меня все идет нормально, но я не понимаю одну часть примеров кода.

В основном приведенный ниже код используется для сравнения объекта Card с другой картой.

- (void) flipCardAtIndex: (NSUInteger)index
{
    Card *card = [self cardAtIndex:index];
    if (card && !card.isUnplayable)
    {
        if (!card.isFaceUp)
        {
            for (Card* otherCard in self.cards)//for-in loop
            {
                if (otherCard.isFaceUp && !otherCard.isUnplayable)
                {
                    int matchScore = [card match:@[otherCard]];
......

И вот как работает cardAtIndex:

-(Card *) cardAtIndex:(NSUInteger)index
{
    if (index < [self.cards count])
        //dot notation is used for property
        //[] is used for method
    {
        return self.cards[index];
    }
    return nil;
}

Вот методы для Match(card*) и Match(playingCard)

Совпадение(карточка*)

-(int) match:(NSArray *)otherCards
{
    NSLog(@"here");
    int score = 0;

    for (Card *card in otherCards)
    {
        if ([card.content isEqualToString:self.content])
            score = 1;
        {
            NSLog(@"Card Match");
        }

    }
    return score;
}

Совпадение(Игральная карта*)

-(int) match: (NSArray *)otherCards;
{
    int score = 0;
    if ([otherCards count] == 1)
    {
        PlayingCard *otherCard = [otherCards lastObject];//the last object in the array
        if ([otherCard.suit isEqualToString:self.suit])
            score = 1;
        else if (otherCard.rank == self.rank)
            score = 4;
        NSLog(@"PlayingCard Match");
    }
    return score; 
}

Это работало просто отлично, но я не понимаю, почему, когда объект Card* вызывает метод, вызывается метод его подкласса PlayingCard. Большое спасибо за помощь мне!


person Haoyu    schedule 22.08.2013    source источник


Ответы (2)


Эта концепция называется Полиморфизм.

Это позволяет вам иметь базовый класс, предоставляющий некоторый интерфейс, и набор подклассов, реализующих эти методы различными способами. Классическим примером является метод класса Drawable draw и его подклассы Circle и Rectangle, которые переопределяют метод draw для отображения себя определенным образом.

То же самое относится и к вашему базовому классу Card, он вызывает свой собственный метод интерфейса match, но поскольку объект на самом деле не является экземпляром Card, а подкласса PlayingCard, вместо этого вызывается метод подкласса для обеспечения конкретной реализации.

person iHunter    schedule 22.08.2013
comment
Спасибо за Ваш ответ! Я понимаю, что экземпляр должен быть подклассом PlayingCard, но я не уверен, как он создается. Когда я создал экземпляр, он относится к подклассу PlayingCard, но поскольку я вызвал метод, чтобы принять его в качестве аргумента и вернуть результат класса Card, я не понимаю, почему он все еще является переменной экземпляра метода PlayingCard. - person Haoyu; 26.08.2013
comment
Посмотрите внимательно на метод cardAtIndex: - он не создает экземпляр Card, вместо этого он возвращает что-то, соответствующее интерфейсу Card, а его реализация просто возвращает один из self.cards, каждый из которых является PlayingCard. Почему он не приводится к типу Card? Что ж, в некоторых языках это возможно, но в Objective-C, как и во многих языках с динамической типизацией, все методы по умолчанию полиморфны. (Сравните с C++, где приведение к Card фактически вызовет методы Card, если вы не объявите их явно как virtual, например, полиморфные). - person iHunter; 26.08.2013
comment
Отличное объяснение. Теперь я понимаю, почему. Спасибо большое! - person Haoyu; 28.08.2013

В файле .m контроллера представления свойство «колода» должно быть инициализировано как класс PlayingCardDeck, а в PlayingCardDeck.m класс карты — PalyingCard. Таким образом, даже если вы объявили свою карту как класс Card, метод, который она вызывает, все равно будет тем же, что и в классе PlayingCard.

person lxmfly123    schedule 23.08.2013