What is the difference from making a new class a child of NPCUnit Class ver. NSObject and using the #import"NPCUnit" class. So far I have been making everything a child of NSObject. When I think of the parent class I say to my self "It gets to use all it's methods and instance variables". If I pound import something I get to say the same thing.
#import is very different from inheritance. #import is a way of telling your class about some other class, framework etc. I think/explain best with analogies so let's say you have a person object and an iPhone object. There is no obvious inheritance relationship here--a person isn't a kind of iPhone and an iPhone isn't a kind of person.
If my person object wanted to manipulate an iPhone object, it would need to
A. know that an iPhone exists, and
B. know all of the things you can do to it.
Because it needs to have this information, it needs to import the header where all of this information about an iPhone is declared. Note that the iPhone doesn't need to know anything about the person object, it just reacts to the messages pass into it. So the Person object reads that there's this thing called an iPhone that has a
BOOL isOn property, and an NSInteger attSignalStrength; property (always < 1) etc. It has methods like -(void) turnVolumeDown. and -(void)insertHeadphones.
Without importing the header for the iPhone class, the Person wouldn't even know the iPhone Class exists (even though they're both in the same project folder in Xcode) so if a method in the Person class tried to create an iPhone object and insertHeadphones, the compiler would freak out.
Inheritance is a completely separate beast. Yes you still need to import the header of the parent class, but an inherited class is a direct descendant of the parent. What this means is that that if a MageUnit object is descended from an NPCUnit class, then when you instantiate a MageUnit object, it will have all of the methods and iVars of the NPCUnit class included as part of itself. So if an NPCUnit class has a method like (void)advanceLevel, then a MageUnit instance could call [self advanceLevel]; Notice how this is different from sending messages to a different object of a different class (like we were discussing with the iPhone example).
This might illustrate it a bit better in pseudocode:
Code:
ParentObject
{
ivar1
ivar2
}
-methodA
-methodB
//
ChildObject: ParentObject
{
ivarY
ivarZ
}
-methodC
-methodD
// When you instantiate a Child Object, it's memory will have:
{
ivar1
ivar2
ivarY
ivarZ
}
// and will have as methods:
-methodA
-methodB
-methodC
-methodD
The ChildObject literally has everything the ParentObject has and more. Note that you're not creating 2 objects here, you're
only instantiating just the child object, but it has all of the ivars of it's parent (and it's parent's parent etc. all the way up to the root object--which is nearly always NSObject). When I say it has the ivars, it literally has the ivars--they are 100% part of the object just as if you'd declared them in the Child's @interface section. They are first class instance variables, and belong to your class just like any you declare in it's @interface.
Why do you underscore the variable names? Is it for easier identification?
Yes, it's a convention that helps me easily identify my instance variables from my local and other variables. It's actually a violation of Apple's guidelines which explicitly reserve the underscore prefix namespace. In my defense, the practice is fairly widespread, and I know good programmers who do it, so I don't feel as bad about breaking this rule.
I have never used '+' class methods, only instance methods '-'. I have to read up on it.
Every time you call [SomeClass alloc] you are using a class method. I think of each class as having 1 golden version of it floating in the sky that is the God of all instances of itself. So in a MageUnit class, there is a golden mage hovering in the netherworld, and all class methods go to him. Class methods are only appropriate for "big picture things" not individuals, such as:
"Hey, MageUnit God, create an enemyMage5 object for me," or "MageUnit God, how many individual mageUnits have you ever created since this program has launched?"
Notice how this question would be inappropriate to ask of billyTheSmellyMage instance, because he may have been "born" after many thousands of other MageUnit instances have been created and destroyed. Any one individual instance wouldn't be around long enough to keep track of that kind of info--thus the role of the Class methods.
I also see you used NSInteger where I have been using 'int'. After writing this message I am going to try and see if I can use operators on NSIntegers to perform math functions.
I'm using NSIntegers instead of ints in all of my code now. You can +, -, or any other kind of operator on them (they're not objects). The only real gotcha is when you print them out with NSLog(). I cast them as (long)someNSInteger and use the %ld to print them out. Otherwise it should be a straight substitution (and you still need to pack them up in NSNumber objects when you need to use objects just like you would with an int). Basically, NSInteger is a tool for making sure your code is 64-bit compliant, and is a good habit to get into using.
When I am at the end of the project my goal was to take goodGuyArmy objectATIndex[1] and have him fight badGuyArmy objectAtIndex[1] using the random roll to then subtract their hit points. I would mix up the array so it could be a level 1 guy against a level 6 guy and not just Level 1 against level 1. The over all goal was to start to learn to use Objects to perform tasks.
I think this is a great, simple project. One thing to consider is that you don't need is to have a separate goodGuy class and a badGuy class. In the code just make a badGuyArmy array and create a bunch of dudes, and then make a goodGuyArmy array and create a bunch of dudes for that. You don't even need to store this state internally in an ivar, because it doesn't really matter--goodGuys and badGuys all have the same stats and abilities.
Now if goodguys were fundamentally different in the things they could do and how they were implemented, then it would probably make sense to create them as different classes. For example if you had special AI functions controlling them and goodGuys/badGuys behaved very differently.
I bought the book Cocoa Recipes for Mac OSX. I think that will be my first book to read. I did also buy the Clean Code you recommended. I am good enough right now to work through a large project. Then I will double back to the Kochan book to start filling in my programing holes.
Thanks very much for your support as I learn!!!
That sounds like a very reasonable approach. I'm happy to help. I've been helped a lot on this forum and in other places, so it's nice to help out others in ways that I am able. I'm still very much learning this stuff myself, so you might be teaching me stuff sometime soon.