Amazon.com Widgets Ex 18-2. Not sure I am missing something
Welcome, Guest. Please login or register.
Did you miss your activation email?
July 30, 2014, 02:04:09 AM
Home Help Search chat Login Register 
News: Read this please.The Great Kangaroo Escape Looking for reviews of the 4th ed on Amazon!   Twitter:  @skochan
                     

+ Official Forum for Programming in Objective-C (the iPhone Programming Language) - Stephen Kochan
|-+ Old Stuff
| |-+ Answers to Exercises
| | |-+ Chapter 18
| | | |-+ Ex 18-2. Not sure I am missing something
Pages: [1] Go Down
Print
Author Topic: Ex 18-2. Not sure I am missing something (Read 503 times)
Nick Harvey
Newbie
*
Posts: 19






on: June 14, 2012, 03:57:30 AM

My answer to Ex 18-2 is a bit different to those posted as my shape classes had evolved into putting common attributes and methods into a GraphicObject class. Even so, I have created a copyWithZone method for my Rectangle and XYPoint classes but I see no difference between using the XYPoint's copy method and just using the normal setter method. If I modify the original Rectangle in any way, the copied rectangle is not modified and vice versa which is what I want.

In my Rectangle copyWithZone method, I see no difference between using
  [newRect setOrigin:[origin copy]];
and
  [newRect setOrigin:origin];

My answer to whether we need a mutable copy method is No as neither object contains mutable items such as arrays, strings or dictionaries. Is this correct?

Here is my code. As always, I appreciate any feedback as I am struggling to understand the complexities of creating mutable and immutable copies.

GraphicObject.h

#import <Foundation/Foundation.h>

@class XYPoint;

@interface GraphicObject : NSObject
{
  int fillColor, lineColor;
  BOOL filled;
  XYPoint *origin; 
}

@property int fillColor, lineColor;
@property BOOL filled;

-(void) printGraphicParameters;
-(void) setOrigin: (XYPoint *) pt;
-(void) translate: (XYPoint *) pt;
-(XYPoint *) origin;
-(float) originX;
-(float) originY;

@end

GraphicObject.m

#import "GraphicObject.h"
#import "XYPoint.h"

@implementation GraphicObject

@synthesize fillColor, lineColor, filled;

-(void) printGraphicParameters
{
  NSLog(@"Graphic Object Parameters for %@ are:", [self class]);
  NSLog(@"  Fill Color:          (%i)", fillColor);
  NSLog(@"  Line Color:          (%i)", lineColor); 
  NSLog(@"  Filled:              (%d)", filled); 
}

-(void) setOrigin: (XYPoint *) pt
{
  if (!origin)
    origin = [XYPoint new];
  origin.x = pt.x;
  origin.y = pt.y;
}

-(void) translate: (XYPoint *) pt
{
  origin = pt;
}

/* As this getters is returning an obect (which is just a pointer), I have created a new object
 in each (with a new pointer) and set the values to it to make sure I protect the values at the
 original pointer.*/
-(XYPoint *) origin
{
  XYPoint *retXYPoint = [XYPoint new];
  retXYPoint.x = origin.x;
  retXYPoint.y = origin.y; 
  return retXYPoint;
}

-(float) originX
{
  return origin.x;
}

-(float) originY
{
  return origin.y;
}

@end

XYPoint.h

#import <Foundation/Foundation.h>

@interface XYPoint : NSObject <NSCopying>
{
  float x, y;
}

@property float x, y;

-(void) setX: (float) xVal andY: (float) yVal;
-(void) print;

@end

XYPoint.m

#import "XYPoint.h"

@implementation XYPoint

@synthesize x, y;

-(id) copyWithZone:(NSZone *)zone
{
  XYPoint *newXY = [[XYPoint allocWithZone:zone] init];
  [newXY setX:x andY:y];
  return newXY;
}

-(void) setX: (float) xVal andY: (float) yVal
{
  x = xVal;
  y = yVal;
}

-(void) print
{
  NSLog(@"(%g,%g)", x, y);
}
@end

Rectangle.h
#import "GraphicObject.h"

@interface Rectangle : GraphicObject <NSCopying>
{
  float width, height;
}

@property float width, height;

-(float) area;
-(float) perimeter;

-(id) initWithWidth: (int) inWidth andHeight: (int) inHeight;

-(void) setWidth: (float) w andHeight: (float) h;

-(void) printParameters;
-(void) draw;

-(BOOL) containsPoint: (XYPoint *) pt;
-(Rectangle *) intersect: (Rectangle *) inRect;
-(XYPoint *) topLeft;
-(float) topLeftX;
-(float) topLeftY;
-(XYPoint *) topRight;
-(float) topRightX;
-(float) topRightY;
-(XYPoint *) bottomLeft;
-(float) bottomLeftX;
-(float) bottomLeftY;
-(XYPoint *) bottomRight;
-(float) bottomRightX;
-(float) bottomRightY;

@end

Rectangle.m
#import "Rectangle.h"
#import "XYPoint.h"

@implementation Rectangle

@synthesize width, height;

-(id) copyWithZone:(NSZone *)zone
{
  Rectangle *newRect = [[Rectangle allocWithZone:zone] initWithWidth:width andHeight:height];
  [newRect setOrigin:[origin copy]];
// No difference
//  [newRect setOrigin:origin];
  [newRect setFillColor:fillColor];
  [newRect setFilled:filled];
  [newRect setLineColor:lineColor];
  return newRect;
}

-(id) initWithWidth: (int) inWidth andHeight: (int) inHeight
{
  self = [super init];
  if (self)
    [self setWidth:inWidth andHeight:inHeight];
 
  return self;
}

-(id) init
{
  return [self  initWithWidth:0 andHeight:0];
}

-(float) area;
{
  return (width * height);
}

- (float) perimeter
{
  return (2 * (width + height));
}

-(void) setWidth: (float) w andHeight: (float) h
{
  width = w;
  height = h;
}

-(void) printParameters
{
  [self printGraphicParameters];
  NSLog(@"Parameters for %@ are:", self.description);
  NSLog(@"  Width:               (%g)", width);
  NSLog(@"  Height:              (%g)", height);
  NSLog(@"  Starting Point:      (%g, %g)", origin.x, origin.y);
  NSLog(@"  Bottom Left Corner:  (%g, %g)", self.bottomLeftX, self.bottomLeftY);
  NSLog(@"  Bottom Right Corner: (%g, %g)", self.bottomRightX, self.bottomRightY);
  NSLog(@"  Top Left Corner:     (%g, %g)", self.topLeftX, self.topLeftY);
  NSLog(@"  Top Right Corner:    (%g, %g)", self.topRightX, self.topRightY);
  NSLog(@"  Area:                (%g)", self.area);
  NSLog(@"  Perimeter:           (%g)", self.perimeter);
}

-(void) draw
{
  for (int counter1 = 1; counter1 <= height; counter1++)
  {
    for (int counter2 = 1; counter2 <= width; counter2 ++)
    {
      if (counter1 == 1 || counter1 == height)
      {
        printf("-");
        if (counter2 == width)
          printf("\n");
      }
      else if (counter2 == 1 || counter2 == width)
      {
        printf("|");       
        if (counter2 == width)
          printf("\n");
      }
      else printf(" ");
    }
  }
}

-(BOOL) containsPoint: (XYPoint *) inPt
{
  // Not sure whether I need to include points on the line. I have chosen not to.
  if (inPt.x > self.bottomLeftX &&
      inPt.x < self.bottomRightX &&
      inPt.y > self.bottomLeftY &&
      inPt.y < self.topLeftY)
    return YES;
  else
    return NO;
}

-(Rectangle *) intersect: (Rectangle *) inRect
{
  BOOL intersectOK = YES;
  Rectangle *retRect = [Rectangle new];
 
  if (inRect.topLeftX < self.bottomRightX && inRect.topLeftY > self.bottomRightY &&
      inRect.bottomRightX > self.topLeftX && inRect.bottomRightY < self.topLeftY)
  {
    retRect.height = inRect.topLeftY - self.bottomRightY;
    retRect.width = self.bottomRightX - inRect.topLeftX;
    //Why doesn't this line work?
    [retRect.origin setX:inRect.topLeftX andY:self.bottomRightY];
    //And these three lines do?
    XYPoint *retOriginPt = [XYPoint new];
    [retOriginPt setX:inRect.topLeftX andY:self.bottomRightY];
    retRect.origin = retOriginPt;
  }
  else if (self.topLeftX < inRect.bottomRightX && self.topLeftY > inRect.bottomRightY &&
           self.bottomRightX > inRect.topLeftX && self.bottomRightY < inRect.topLeftY)
  {
    retRect.height = self.topLeftY - inRect.bottomRightY;
    retRect.width = inRect.bottomRightX - self.topLeftX;
    //Why doesn't this line work?
    [retRect.origin setX:self.topLeftX andY:inRect.bottomRightY];
    //And these three lines do?
    XYPoint *retOriginPt = [XYPoint new];
    [retOriginPt setX:self.topLeftX andY:inRect.bottomRightY];
    retRect.origin = retOriginPt;
  }
  else
    intersectOK = NO;
 
  if (intersectOK)
    return retRect;
  else
  {
    NSLog(@"Rectangles do not intersect");
    return NULL;
  }
}

-(XYPoint *) bottomLeft
{
  XYPoint *retXYPoint = [XYPoint new];
  [retXYPoint setX:origin.x andY:origin.y];
  return retXYPoint;
}

-(float) bottomLeftX
{
  return origin.x;
}

-(float) bottomLeftY
{
  return origin.y;
}

-(XYPoint *) bottomRight
{
  XYPoint *retXYPoint = [XYPoint new];
  [retXYPoint setX:(origin.x + width) andY:origin.y];
  return retXYPoint;
}

-(float) bottomRightX
{
  return origin.x + width;
}

-(float) bottomRightY
{
  return origin.y;
}

-(XYPoint *) topLeft
{
  XYPoint *retXYPoint = [XYPoint new];
  [retXYPoint setX:origin.x andY:(origin.y + height)];
  return retXYPoint;
}

-(float) topLeftX
{
  return origin.x;
}

-(float) topLeftY
{
  return origin.y + height;
}

-(XYPoint *) topRight

  XYPoint *retXYPoint = [XYPoint new];
  [retXYPoint setX:(origin.x + width) andY:(origin.y + height)];
  return retXYPoint;
}

-(float) topRightX
{
  return origin.x + width;
}

-(float) topRightY
{
  return origin.y + height;
}

@end
Logged
Pages: [1] Go Up
Print
Jump to:



Login with username, password and session length

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!
Entire forum contents (c) 2009 classroomM.com. All rights reserved.