Amazon.com Widgets Excercise 4.7
Welcome, Guest. Please login or register.
Did you miss your activation email?
November 01, 2014, 04:47:40 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
|-+  Programming in Objective-C, 4th edition
| |-+  Exercises
| | |-+  Chapter 4
| | | |-+  Excercise 4.7
Pages: [1]   Go Down
Print
Author Topic: Excercise 4.7  (Read 1962 times)
pbb76
Newbie
*
Posts: 2


Email




« on: December 25, 2011, 09:56:29 AM »

This seems to work - not sure if its the best way or not - still very new to Obj-C!

Code: (Objective-C)
@interface Rectangle : NSObject 

-(void) setWidth: (int) w;
-(void) setHeight: (int) h;
-(int) width;
-(int) height;
-(int) area;
-(int) perimeter;

@end

@implementation Rectangle
{
    int width, height, area, perimeter;
}

-(void) setWidth:(int)w
{
    width = w;
}

-(void) setHeight:(int)h
{
    height = h;
}

-(int) height
{
    return height;
}

-(int) width
{
    return width;
}

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

-(int)perimeter
{
    return (width+height)*2;
}
@end

int main (int argc, char * argv[])
{
    @autoreleasepool {
        Rectangle *myRectangle = [[Rectangle alloc] init];
        
        // set height
        [myRectangle setHeight:10];
        
        // set width
        [myRectangle setWidth:30];
        
        NSLog(@"The Perimeter is: %i cm", [myRectangle perimeter]);
        NSLog(@"The Area is: %i cm", [myRectangle area]);
    }
    return 0;
}

Results:

2011-12-25 16:55:29.125 prog1[976:707] The Perimeter is: 80 cm
2011-12-25 16:55:29.128 prog1[976:707] The Area is: 300 cm
Program ended with exit code: 0
Logged
jgelling
Newbie
*
Posts: 27






« Reply #1 on: January 01, 2012, 12:06:54 AM »

Area and perimeter are just methods - the only instance variables for a Rectangle should be its width and height. By including area and perimeter as integer ivars in your @implementation section you've created ambiguity between the methods area and perimeter - which calculate those values dynamically when called - and the instance variables which are never set correctly in your code.

The code produces the right results because there are no getter methods for the ivars area and perimeter, so the method is called instead. But really area and perimeter need to be removed, unless you're going to constantly update them as the user changes the height and width of the rectangle (which would be unnecessary as these values can be generated dynamically from the width and height alone).

When working with objects, ask yourself: what are the intrinsic properties of this object? If you know the width and height of a rectangle, you can calculate the area or the perimeter, so only the width and height are intrinsic and only they should be ivars. But even if you wanted to store non-intrinsic ivars, you should make setter and getter methods for them and ensure they're updated based on changes made to other properties of the object.
Logged
pbb76
Newbie
*
Posts: 2


Email




« Reply #2 on: January 02, 2012, 05:07:06 AM »

Thanks! Think that makes sense - still find it all a bit confusing right now, but trying hard to understand it Smiley
Logged
jimmac
Newbie
*
Posts: 13






« Reply #3 on: February 29, 2012, 07:26:19 PM »

The answers that I've read for exercise 4.7 put the calculation of area and perimeter into the implementation section of main.m.

An option would be to put these calculations into the program section, like this:

Code: (Objective-C)
#import <Foundation/Foundation.h>

//--- @interface section ---

@interface Rectangle : NSObject

-(void) setWidth: (int) w;
-(void) setHeight: (int) h;
-(int) width;
-(int) height;

@end

//---@implementation section---

@implementation Rectangle
{
    int width;
    int height;
}

// Setter methods

-(void) setWidth:(int) w
{
    width = w;
}

-(void) setHeight:(int) h
{
    height = h;
}

//Getter methods

-(int) width;
{
    return width;
}

-(int) height;
{
    return height;
}

@end

//---program section---

int main (int argc, const char * argv[])
{
   
    @autoreleasepool {
        Rectangle *myRect;
       
        // Create an instance of a Rectangle
        myRect = [Rectangle alloc];
        myRect = [myRect init];
       
        // Set myRect w, h
        [myRect setWidth:10];
        [myRect setHeight:5];
       
        // Calculate area and perimeter by getting w and h
        int area = [myRect width] * [myRect height];
        int perimeter = 2 * ([myRect width] + [myRect height]);
       
        // Display myRect info
        NSLog(@"For a rectangle of width %i and height %i units, the area is %i sq. units and the perimeter is %i units.", [myRect width], [myRect height], area, perimeter);
    }
    return 0;
}


Is there a preference/best practice for the placement of this sort of calculation in Objective-C?

Thanks!
Logged
Bunchadna
Newbie
*
Posts: 27






« Reply #4 on: April 14, 2012, 02:07:33 PM »

Area and perimeter are just methods - the only instance variables for a Rectangle should be its width and height. By including area and perimeter as integer ivars in your @implementation section you've created ambiguity between the methods area and perimeter - which calculate those values dynamically when called - and the instance variables which are never set correctly in your code.

The code produces the right results because there are no getter methods for the ivars area and perimeter, so the method is called instead. But really area and perimeter need to be removed, unless you're going to constantly update them as the user changes the height and width of the rectangle (which would be unnecessary as these values can be generated dynamically from the width and height alone).

When working with objects, ask yourself: what are the intrinsic properties of this object? If you know the width and height of a rectangle, you can calculate the area or the perimeter, so only the width and height are intrinsic and only they should be ivars. But even if you wanted to store non-intrinsic ivars, you should make setter and getter methods for them and ensure they're updated based on changes made to other properties of the object.
Are you saying that they shouldn't appear in the @interface section at all?  The exercise in the text shows them in the @interface section.
Logged
rue
Jr. Member
**
Posts: 53






« Reply #5 on: April 22, 2012, 11:58:34 AM »

I did things just slightly different.

Code: (Objective-C)
@implementation Rectangle  
{  
    int width, height, area, perimeter;  
}  
area and perimeter probably needs to be removed here... since they are not instance variables.

And I would change the method names from  area and perimeter to
ComputeArea
ComputePerimeter

so it will be
area = [myRect ComputeArea];
perimeter = [myRect ComputePerimeter];

It makes it obvious reading the code that area and perimeter are methods, i.e. computed values, and not instance variables.  



« Last Edit: April 22, 2012, 12:02:23 PM by rue » Logged
clouded
Full Member
***
Posts: 123






« Reply #6 on: May 09, 2012, 11:17:46 AM »

Here's what I have on this exercise, but I did notice that the way you call variables differs from mine in the NSLog in main:

Code: (Objective-C)
// Suppose you are developing a library of routines to 
// manipulate graphical objects. Start by defining a new class
// called Rectangle. For now, just keep track of the rectangle’s
// width and height. Develop methods to set the rectangle’s width
// and height, retrieve these values, and calculate the rectangle’s
// area and perimeter. Assume that these rectangle objects describe
// rectangles on an integral grid, such as a computer screen. In
// that case, assume that the width and height of the rectangle are
// integer values.
//
// Here is the @interface section for the Rectangle class:
// @interface Rectangle: NSObject
// -(void) setWidth: (int) w;
// -(void) setHeight: (int) h;
// -(int) width;
// -(int) height;
// -(int) area;
// -(int) perimeter;
// @end
//
// Write the implementation section and a test program to test your new class and methods.

#include <Foundation/Foundation.h>

@interface Rectangle: NSObject
    -(void) setWidth: (int) w;
    -(void) setHeight: (int) h;
    -(int) width;
    -(int) height;
    -(int) area;
    -(int) perimeter;
    -(void) print;
@end

@implementation Rectangle
{
    int width, height;
}

-(void) setWidth: (int) w
{
    width = w;
}

-(void) setHeight: (int) h
{
    height = h;
}

-(int) width
{
    return width;
}

-(int) height
{
    return height;
}

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

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

-(void) print
{
    NSLog(@"Width = %i Height = %i", width, height);
}
@end

int main(int argc, const char *argv[]) {
    
    @autoreleasepool {
        Rectangle *myRectangle = [[Rectangle alloc]init];
        [myRectangle setWidth: 2];
        [myRectangle setHeight: 3];
        [myRectangle print];
        NSLog(@"Area = %i Perimeter = %i", myRectangle.area, myRectangle.perimeter);
    }
    return 0;
}
Output:
Width = 2 Height = 3
Area = 6 Perimeter = 10
« Last Edit: May 11, 2012, 05:33:17 PM by clouded » 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.