inheritance problem

Discussion in 'iOS Programming' started by grandM, Apr 15, 2014.

  1. grandM, Apr 15, 2014
    Last edited: Apr 15, 2014

    grandM macrumors 6502a

    grandM

    Joined:
    Oct 14, 2013
    #1
    Hi, I don't understand why I can't access self.cardButtons in the child class SetCardCardgameViewController. The parent is CardgameViewController.

    CardgameViewController.h:
    Code:
    #import <UIKit/UIKit.h>
    #import "Deck.h"
    
    @interface CardgameViewController : UIViewController
    - (void) updateUI;
    
    //  protected
    //  for subclasses
    
    - (Deck *)createDeck;
    
    // must be overriden in SetCardGameViewController as contents is not to be used for instance
    - (NSAttributedString *)titleForCard: (Card *)card;
    - (UIImage *)backgroundImageforCard: (Card *)card;
    
    @end
    
    CardgameViewController.m
    Code:
    #import "CardgameViewController.h"
    //#import "PlayingCardDeck.h"
    #import "CardMatchingGame.h"
    
    @interface CardgameViewController ()
    
    @property (strong, nonatomic) CardMatchingGame *game;
    @property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *cardButtons;
    @property (weak, nonatomic) IBOutlet UILabel *scoreLabel;
    @property (weak, nonatomic) IBOutlet UISegmentedControl *matchMode;
    @property (weak, nonatomic) IBOutlet UILabel *status;
    @property (weak, nonatomic) IBOutlet UISlider *historySlider;
    @property (weak, nonatomic) IBOutlet UILabel *historyOverview;
    
    @end
    
    SetCardCardgameViewController.h
    Code:
    #import "CardgameViewController.h"
    
    @interface SetCardCardgameViewController : CardgameViewController
    
    @end
    
    SetCardCardgameViewController.m
    Code:
    #import "SetCardCardgameViewController.h"
    #import "SetCardDeck.h"
    #import "SetCard.h"
    
    @interface SetCardCardgameViewController ()
    
    @end
    
    @implementation SetCardCardgameViewController
    
    - (void)updateUI
    {
        for (UIButton *cardButton in self.cardButtons) {
            
        }
    
    }
    
    this last self.cardButtons isn't recognized. But cardButtons is a property of the parent class. Why isn't it recognized? I agree it's privately declared but as SetCardCardgameViewController is a child of CardgameViewController, I thought I could access all its properties and methods. Or am I mistaken?
     
  2. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #2
    It isn't recognized because the property isn't declared in the superclass. Instead, it's declared in a category of the superclass, and that declaration isn't in any header file you've shown, so it isn't importable by any other .m files.

    Here's your code:
    Code:
    CardgameViewController.m
    Code:
    #import "CardgameViewController.h"
    //#import "PlayingCardDeck.h"
    #import "CardMatchingGame.h"
    
    @interface CardgameViewController ()
    
    @property (strong, nonatomic) CardMatchingGame *game;
    @property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *cardButtons;
    @property (weak, nonatomic) IBOutlet UILabel *scoreLabel;
    @property (weak, nonatomic) IBOutlet UISegmentedControl *matchMode;
    @property (weak, nonatomic) IBOutlet UILabel *status;
    @property (weak, nonatomic) IBOutlet UISlider *historySlider;
    @property (weak, nonatomic) IBOutlet UILabel *historyOverview;
    
    @end
    
    First, notice what file it's in: CardgameViewController.m. That is, it's in the implementation of CardgameViewController. Since you're not importing a .m file (and you shouldn't), the properties declared in the category are unknown outside this specific .m file.

    Next, look at the @interface in that file. What you've done is declared a nameless category on CardgameViewController. These properties (or methods, if there were any) would be visible to other classes if the category were declared in an importable .h file, but you didn't do that.


    I'm guessing, but it looks to me like you don't understand the distinction between the interface of a class, and a category declared on a class. For example, you've got an empty category in SetCardCardgameViewController.m. What purpose does this serve? If you don't know, remove it.

    Please explain exactly what book or tutorial you're learning from, and exactly what point you're at. If categories have been covered, then review that material. If you have no idea what a category is, then you're using things you haven't learned yet, and you're putting things (like properties) in the wrong place (like inside a non-public category).

    Knowing what book or tutorial you're learning from will help us know what to suggest to correct the problem.
     
  3. grandM thread starter macrumors 6502a

    grandM

    Joined:
    Oct 14, 2013
    #3
    Hi thanks for answering. A few months ago I went through a book from Kochan on objective-c. Much has gone forgotten though. Now I'm following the Stanford Itunes course. I'm at lesson 6, assignment 3.

    I must admit the distinction between category and interface has gone vague. I thought what was declared in the .h file was accessible to all. What went inside the .m file was private. So if I put properties in the @interface in the .m file they couldn't be seen by other classes. I also thought that the properties in this .m file couldn't be gotten or set by another class. For instance another class wouldn't be able to perform the getter (or perform a setter) of status.

    I did think I could access these properties if the class was a subclass of the class containing the properties (through inheritance), even if they were declared in the implementation. But apparently this isn't the case: if the subclass wants to access the properties of the superclass they must be declared in the .h file. Am I correct or am I making more mistakes?
     
  4. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #4
    It is.

    The problem is that the properties aren't in a .h file. If they were, and if the class that wanted to use them then imported the .h file, then the properties would be available. Since that isn't what you did, then you don't get that result.

    They aren't directly visible, but that's not the same thing as @private. And Objective-C doesn't allow @private on methods (or properties, IIRC), which means they're @public.

    Since they're @public, that means any class that can either get a declaration or use reflection will be able to see the properties. You didn't do either of those, so the properties don't exist as far as your posted code is concerned.


    That's a side-effect of declaring the interface somewhere other than a .h file. It has no effect on @private vs. @public.

    If the properties were in a header file, and another class imports that header, then the properties are accessible.


    That's correct.

    I think you should review the fundamentals of properties, visibility (@private, @public, etc.), and what a category actually is.

    Right now, you're making fundamental errors because your recollection is faulty. Brush up the fundamentals first.
     
  5. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
  6. grandM thread starter macrumors 6502a

    grandM

    Joined:
    Oct 14, 2013
    #6
    Indeed I've just read through some apple online documentation on objective-c
    I was using extensions
    Extension properties are private
    If I want to subclass I must move some of them to the public header or into a category (less recommended)
     

Share This Page