Inheritance

Inheritance in Objective-C is much like that of it's peer Object Oriented languages. (Dynamic binding comes later.) To demonstrate inheritance in action, I'll create a subclass of GasCan called MarineGasCan. I'll also modify GasCan a bit so that I can demonstrate the impact of private vs. protected properties.

The updated GasCan interface file (GasCan.h):

  1. #import <Foundation/Foundation.h>
  2.  
  3. @interface GasCan : NSObject {
  4. @private
  5. int size;
  6. @protected
  7. BOOL spoutOpen;
  8. BOOL valveOpen;
  9. }
  10.  
  11. @property (nonatomic) float level;
  12.  
  13. -(id) initWithSize: (int)x;
  14. -(id) init;
  15. -(void) pourContents;
  16. -(int) size;
  17. -(void)openSpout: (BOOL)x andValve: (BOOL)y;
  18. @end

The updated GasCan implementation file (GasCan.m):

  1. #import "GasCan.h"
  2.  
  3. @implementation GasCan
  4.  
  5. @synthesize level;
  6.  
  7. // Call the designated initializer and default the can to a size of 5
  8. -(id) init {
  9. return [self initWithSize:5];
  10. }
  11.  
  12. // The designated initializer
  13. -(id) initWithSize: (int)x {
  14. self = [super init];
  15. if (self) {
  16. size = x;
  17. }
  18. return self;
  19. }
  20.  
  21. -(void) pourContents {
  22. if (!spoutOpen) {
  23. NSLog(@"You can't pour the contents because the spout is not open.");
  24. } else {
  25. float increment = (valveOpen) ? .1 : .01;
  26. while (level > 0.0) {
  27. NSLog(@"Glug glug glug");
  28. level -= increment;
  29. }
  30. level = 0;
  31. }
  32. }
  33.  
  34. -(void)setLevel: (float)l {
  35. level = (l > size) ? size : l;
  36. }
  37.  
  38. -(int) size {
  39. return size;
  40. }
  41.  
  42. -(void)openSpout: (BOOL)x andValve: (BOOL)y {
  43. spoutOpen = x;
  44. valveOpen = y;
  45. }
  46.  
  47. @end

The new MarineGasCan interface file (MarineGasCan.h):

  1. #import "GasCan.h"
  2.  
  3. enum engineType { twoStroke, fourStroke };
  4.  
  5. @interface MarineGasCan : GasCan
  6. @property float oilLevel;
  7. -(id) initWithSize: (int)x andType: (enum engineType)y;
  8. -(float) getOilToGasRatio;
  9. @end

The new MarineGasCan implementation file (MarineGasCan.m):

  1. #import "MarineGasCan.h"
  2. #import "GasCan.h"
  3.  
  4. @implementation MarineGasCan {
  5. enum engineType canType;
  6. }
  7. @synthesize oilLevel;
  8.  
  9. // Call the designated initializer and default the can to a size of 5
  10. -(id) init {
  11. return [self initWithSize:3 andType: fourStroke];
  12. }
  13.  
  14.  
  15. -(id) initWithSize: (int)x andType: (enum engineType)y {
  16. self = [super initWithSize:x];
  17. if (self) {
  18. canType = y;
  19. }
  20. return self;
  21. }
  22.  
  23.  
  24. -(void) pourContents {
  25. if (!spoutOpen) {
  26. NSLog(@"You can't pour the contents because the spout is not open.");
  27. } else {
  28. if ((canType == twoStroke) && (oilLevel == 0)) {
  29. NSLog(@"WARNING: This is a 2-stroke gas can, but there's no oil!");
  30. } else if ((canType == fourStroke) && (oilLevel > 0)) {
  31. NSLog(@"WARNING: This is a 4-stroke gas can, but there's oil in it!");
  32. }
  33. // Pour more slowly than a generic gas can, since we're probably on the water
  34. // float increment = (valveOpen) ? .1 : .01;
  35. float increment = (valveOpen) ? .09 : .005;
  36. while ([super level] > 0.0) {
  37. NSLog(@"Glug glug glug");
  38. [super setLevel: [super level] - increment];
  39. }
  40. super.level = 0;
  41. }
  42. }
  43.  
  44. -(float) getOilToGasRatio {
  45. if (self.level == 0) {
  46. return 0;
  47. }
  48. return oilLevel / self.level;
  49. }
  50.  
  51. @end

And lastly, an updated main.m file:

  1. #include "GasCan.h"
  2. #include "MarineGasCan.h"
  3.  
  4. int main(int argc, char * argv[]) {
  5. @autoreleasepool {
  6. MarineGasCan *gc = [[MarineGasCan alloc] init];
  7. [gc setLevel:7.2];
  8. [gc setOilLevel:0.5];
  9. NSLog(@"Oil to gas ratio: %f", gc.getOilToGasRatio);
  10. NSString *message = @"The level in your gas can is: ";
  11. NSLog(@"%@ %f",message, gc.level);
  12.  
  13. [gc pourContents];
  14.  
  15. [gc openSpout:true andValve:true];
  16.  
  17. [gc pourContents];
  18.  
  19. NSLog(@"%@ %f",message, [gc level]);
  20. }
  21. }

The following sections will describe the code in more detail