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
|