Hi I had this assignment for my class:
Implement a class named Box that will have the following attributes and methods:
int length, width, height
String color
Constructor method that:
will initialize the 3 integers to 10, 8, 6
will initialize the color to “black”
A setter and getter method for each of the 4 attributes
A method to get the volume of the box
A method to get the surface area of the box (all six sides)
I have all my getters and setters for length width and color. My only problem now is that for volume it will not calculate properly if I set the values to be different.
It only takes the initialized values. Any Ideas to go about it? My code is below for the class. example I could .setLength(7) and instead of printing the total 7*8*6, it prints out the total of 10*8*6.
public class Box
{
private int height = 6;
public void se(int height){
this.height=height;
}
public int getHeight(){
return height;
}
private int width = 8;
public void setWidth(int width){
this.width=width;
}
public int getWidth(){
return width;
}
private int length= 10;
public void setLength(int length){
this.length=length;
}
public int getLength(){
return length;
}
private String color="Black";
public void setColor(String color){
this.color=color;
}
public String getColor(){
return color;
}
private int vol=length*width*height;
public void setVol(int vol){
this.vol=vol;
}
public int getVol(){
return vol;
}
}
Get rid of the vol property and the setVol setter; that's not part of the spec for the class and is the root cause of your problems. Rewrite getVol to compute the volume from the length, width, and height each time it is called.
Your current design doesn't work because vol is not recalculated whenever length, width, or height is changed. You could keep your current set of fields and rewrite the dimension setters to recalculate the vol property each time one is called. That would speed up the getVol getter method at the cost of greater complexity for the class design and slower setter methods. It's a trade-off that you can make or not, as you see fit. However, you need to get rid of the setVol method, because when you set the volume, there's no way to know how to set the dimensions so that the values are consistent.
You need to create a getter function for vol
e.g.
public int getVol () {
vol=length*width*height;
return vol;
}
of course the setting of the intermediate vol is not necessary.
and you could just
return length*width*height;
This ensure that the current vol is always correctly calculated.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 months ago.
Improve this question
public class Wall {
private double width;
private double height;
public Wall() {}
public Wall(double width, double height) {
this.setHeight(height); // using method to set the required fields. //This method is called with unexpected behavior.
this.setWidth(width); // This is not getting called?
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
if (width <= 0) {
this.width = 0;
System.out.println("INVALID VALUE - The width of the wall is updated to :" + 0.0);
} else {
this.width = width;
System.out.println("The width of the wall is updated to :" + width);
}
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
if (height <= 0) {
this.height = 0;
System.out.println("INVALID VALUE - The width of the wall is updated to :" + 0.0);
} else {
this.height = height;
System.out.println("The height of the wall is updated to :" + height);
}
}
public double getArea() {
return width * height;
}
}
//OUTPUT
The width of the wall is updated to :10.0 \\ Expected
INVALID VALUE - The width of the wall is updated to :0.0 \\ not expected
//OUTPUT when parameter order in constructor is reversed
INVALID VALUE - The width of the wall is updated to :0.0 \\expected
The height of the wall is updated to :10.0 \\expected
The goal was to avoid code repetition and I chose to use the setter method in constructor. Also assuming since I am using methods and providing appropriate parameters, the order of the parameter should not matter.
I am not sure if it is supposed to work that way. I see that the method is being called with unexpected behavior.
Few doubts I have regarding the above
Not all methods are getting called in the constructor
Can these setter methods be static and perform operation on the object being created?
What would be the right way to do this?
Thank you
I see that the method is being called with unexpected behavior.
setHeight() actually performs as expected but it is not implemented as you'd expect it. You probably copied it from setWidth() and forgot to change the message so it would print "INVALID VALUE - The width of the wall is updated to : xxx".
the order of the parameter should not matter
The order in which you define the parameters doesn't matter from a technical point of view (unless you have a vargs parameter which needs to be last). However the order of definition leads to the requirement of providing values in the same order when calling the constructor.
Example: Wall(double width, double height) defines the 1st parameter is width and the 2nd is height.
Assume the following:
double width = 5.0;
double height = 7.0;
Wall w = new Wall(height, width);
Here, the names of the parameters don't matter but order does, i.e. w now has a width of 7 and a height of 5 even though the parameters were named otherwise.
What shouldn't matter in most cases is the order in which you call the setters inside the constructor - as long as they're independent.
This means the following 2 should be equivalent:
public Wall(double width, double height) {
this.setHeight(height);
this.setWidth(width);
}
public Wall(double width, double height) {
this.setWidth(width);
this.setHeight(height);
}
When would order matter? If setters were depending on it - not a good style though. Suppose setHeight() would check that height > width. Now if you'd not call setWidth() first setHeight() might behave differently. However, I repeat: this it not good style and should be avoided!
Not all methods are getting called in the constructor
Not sure what you're referring to but constructors don't have to call any method nor do you have to call all the setters there. It really depends on what you want to achieve.
Use constructors for mandatory parameters and setters for mutable ones (and potentially optional). Mutable parameters are those that could be changed after constructing an object, immutable ones should not change - there shouldn't be any setter for those (ideally declare those final and the compiler will complain about setters for those).
Summary:
mandatory + immutable parameters: use constructor only
mandatory + mutable parameters: use constructor which can call setters
optional + mutable parameters: use setters
optional + immutable parameters: use constructor only, potentially via constructor overloads
Can these setter methods be static and perform operation on the object being created?
No, setters should never be static because you'd need to pass the object anyway and thus it's cleaner to just have the setters there.
However, a constructor can call static methods if necessary. Suppose you have a condition to check that width < height which you'd want to call in the constructor and the setters. This could then look like this (simplified and lacking a lot of best practices to keep things simple):
//example of constructor calling the static method
public Wall(double width, double height) {
//check the condition on the input parameters
if( !checkCondition(width, height) ) {
throw new IllegalArgumentException("width >= height");
}
this.setHeight(height);
this.setWidth(width);
}
//example of setter calling the static method
public void setWidth(double width) {
//only set if the condition is met
if(checkCondition(width, this.height) {
//rest of your code
} else {
System.err.println("width would be < height, thus not updating width");
}
}
private static boolean checkCondition(double width, double height) {
return width < height;
}
I’ve never used a separate file for a driver in Java. I’m used to just using a main method. I’ve used separate files in Python but Java is new. Below is my code for each class (“Rectangle” and “Driver”), each from separate files.
Update with the methods changed to static: Don’t pay attention to the change in class names or formatting…I’m just tweaking so it will work with MyProgrammingLab. I still have to add in parameters for length and width being between 0.0 and 20.0 only (easy if-else statements).
import java.util.Scanner;
public class Driver{
public static void main(String[] args) {
Scanner input = new Scanner( System.in);
System.out.print("Enter length of rectangle:");
double length = input.nextDouble();
System.out.print("Enter width of rectangle:");
double width = input.nextDouble();
Rectangle Perimeter = new Rectangle(length, width);
Perimeter.getPerimeter();
Rectangle Area = new Rectangle(length, width);
Area.getArea();
System.out.printf("Area: %.1f, Perimeter: %.1f",Rectangle.getArea(),Rectangle.getPerimeter());
}
}
final class Rectangle {
private static double mLength;
private static double mWidth;
public Rectangle(double length, double width){
mLength = length;
mWidth = width;
}
public double getLength(){
return mLength;
}
public double getWidth(){
return mWidth;
}
public static double getArea(){
double area = mWidth*mLength;
return area;
}
public static double getPerimeter(){
double perimeter = (mWidth*2)+(mLength*2);
return perimeter;
}
}
It makes more sense to create a Rectangle object with it's length & width, so use your overloaded Rectangle constructor by passing the length and width arguments (entered by user) as shown below:
Rectangle Perimeter = new Rectangle(length, width);
the constructor Rectangle() is undefined. Can anyone help?
The important point is that when you have an overloaded constructor like in your Rectangle class (where there are no default i.e., no argument constructors written), you can't create an object using new Rectangle();, this is because compiler doesn't add the default constrcutor automatically for you. I suggest look here for more details on this.
Also, if you wanted to print the Rectangle object with length & width details, you need to override toString() method from java.lang.Object method as shown below:
public class Rectangle {
private double mLength;
private double mWidth;
//add your code here as is
#Override
public String toString() {
return "Rectangle [mLength=" + mLength + ", mWidth=" + mWidth + "]";
}
}
The default constructor is provided by compiler if there are no constructor written explicitly.
But if you explicitly write any constructor in the class, then whenever you call a constructor, be it no-argument or with arguments, it will always look for explicitly defined constructor in class.
And, this is logically correct since, if you want to block creation of objects without any data in it, adding a constructor with argiment is the way to go.
So either explicitly write a no argument constructor in Rectangle and use setter to set its attributs, or just use the argument constructor in your method.
Add to Rectangle.class an empty constructor :
public Rectangle() {
}
Or Use constructor declared with parameters in your method
Rectangle rectangle = new Rectangle(length, width);
In your case you are using the rectangle object wrong.
I think what you looking to do is this :
Rectangle rectangle = new Rectangle(length , width );
System.out.printf("Area: %.1f, Perimeter: %.1f",rectangle.getArea() ,rectangle.getPerimeter());
I already wrote a class Geom that represents three-dimensional, geometrical forms and works with the attributes double dx, dy, dz (the coordinates of the form) and String colour (the colour of the form). Now I am supposed to get more specific, and I want to write a class Cube that extends Geom and that works furthermore with the attribute edge length, in order to calculate things like the volume or area of the form.
In order to do so, I need to write a method private double length, which saves the length of the edges. Besides that, I need to implement get- and set-methods.
This should be quite easy actually, but I don't what I have to do here. I started like this:
public class Cube extends Geom {
int edge;
public Cube (double dx, double dy, double dz, String colour, double edge) {
super(dx, dy, dz, colour);
edge = ///I don't know what do to here
}
private double length(double edge) {
this.edge = edge;
return this.edge;
}
public double getEdge() {
double a = length();
return a;
}
public void setEdge() {
this.edge = edge
}
...
This doesn't seem to make much sense though. I receive two errors, one telling me that this.edge = edge is a lossy conversion from double to int and one telling me that double a = width(); isn't possible because the method width() cannot be applied to the given types. I don't quite see the sense of "saving" the length first, then getting it and setting it in the end.
public class Cube extends Geom {
first of all should encapsulate variables like this and create getter and setter for them.
private int edge;
public Cube (double dx, double dy, double dz, String colour, int edge) {
super(dx, dy, dz, colour);
if you want to be able construct the Geom object with a given edge
you need something like, and change the parameter type to int
this.edge=edge;
this will set the given parameter to your variable 'this' keyword means that you want to invoke to this class edge variable, as the parameter name is the same.
I don't know why you created method length here what it should return ??
As far as i can see it returns the edge, then its the getter job to do so.
}
private double length(double edge) {
this.edge = edge;
return this.edge;
}
You expect to return double while your edge variable is an int, probably want this.
public int getEdge() {
return edge;
or
return this.edge;
it doest matter on that point
}
and the setter should take a value that matches the variable
again you dont necessarily need to say this.edge as the compiler will know what to do as this is the only edge variable here.
public void setEdge(int value) {
this.edge = value;
}
then you can do your calculations and stuff in the length method and parse it to double if you need to, or if need double in the first place, just change the type of the edge to double
I have a class Rectangle laid out like this:
package Inheritance;
/**
*
* #author Jacob
*/
public class Rectangle {
final private int length;
final private int width;
public Rectangle (int l, int w)
{
length = l;
width = w;
}
public int getLength ()
{
return length;
}
public int getWidth ()
{
return width;
}
#Override
public String toString ()
{
return String.format ("Rectangle (%dX%d)", length, width);
}
}
I then need to create class square in the following way:
ad Square:
Square extends Rectangle /
No fields are declared in class Square /
It has a parameterized constructor with (only) one parameter /
The parameter is used to initialize both fields of Rectangle /
It has a method called getSide to expose the side-length of the square /
Override the toString method so that it will return a String of the following form: / Square(side) e.g. Square(4)
The values for the sides are going to be hard coded. Rectangle is going to have a width of 4. In order to get the side of the square to be 4 do I create an instance of rectangle and call the method getWidth and set that as the side length. Thats how I would think to do it but in that case I would only be using one of the fields so, My question is how do I initialize both fields? Can I call Rectangle and make length and width equal or is there some other way I should do it?
Here is the code for my Square class:
public class Square {
public Square (int side)
{
super(side, side);
}
public int getSide ()
{
return side;
}
#Override
public String toString ()
{
return String.format ("Square (%d)", side);
}
}
For the line super(side, side) I get the error constructor Object in class Object cannot be applied to given types. Required no arguments, found int, int. For my return statements I get that it cannot find the variable side.
The values for the sides are going to be hard coded.
I assume that you mean that you will hardcode the values for the width and length when you create a Rectangle and Square object (for example in main()). These values should absolutely not be hardcoded any where in the Rectangle and Square classes.
Rectangle is going to have a width of 4. In order to get the side of the square to be 4 do I create an instance of rectangle and call the method getWidth and set that as the side length.
Not at all. Rather, Square should have its own constructor which calls the Rectangle constructor with the same value for both the width and length:
public Square(int side) {
super(side, side); // Set the width and length to the same value.
}
I know there is an easy solution to this problem but it's driving me crazy. Why is there an error when I want to print the new Rectangle? any help appreciated!
public class Rectangle {
public Rectangle(int x, int y, int width, int length) {
x = 5;
y = 10;
width = 20;
length = 30;
Rectangle box = new Rectangle(5, 10, 20, 30);
System.out.println(new Rectangle());
}
}
There are several problems with your code. First, you may not want to instantiate a Rectangle in the constructor of Rectangle as will lead to infinite recursion. The second problem is that you are calling a constructor that does not exist.
When you write:
new Rectangle()
the Java compiler will look for a constructor in the Rectangle class that accepts no arguments. But your code does not have such a constructor. You can add one like this:
public Rectangle(){
//Your code here to instantiate a default rectangle
}
Usually a constructor is used to set the values of the instance variables in a class rather than to execute code the way you have written it. You can move those lines that are creating rectangles into a main method to test the code.
Here is some code that does what I think you want it to:
public class Rectangle
{
int x, y, width, length; //declares the class's fields
public Rectangle(int x, int y, int width, int length)
{
this.x = x; //initializes the field x to the value of the local variable x
this.y = y; //initializes the field y to the value of the local variable y
this.width = width; //initializes the field width to the value of the local variable width
this.length = length; //initializes the field length to the value of the local variable length
System.out.println(this); //prints this object. should look similar to "Rectangle#1246889"
}
}
Please take a basic java tutorial (e.g. Providing Constructors for Your Classes), it will make your life easier.
You are calling a non-parameterized/default constructor from a parameterized constructor. The JVM in this case unable to create the default constructor. Hence in this case you need to include non-parameterized constructor explicitly into your class.
public class Rectangle {
public Rectangle(int x, int y, int width, int length) {
x = 5;
y = 10;
width = 20;
length = 30;
Rectangle box = new Rectangle(5, 10, 20, 30);
System.out.println(new Rectangle());
}
public Rectangle(){}
}
This will be error free.
First, the code (as you have provided it) can not possibly compile: you haven't declared x, y, width and height as member variables (fields) of your Rectangle. E.g.
// I'm assuming you want these private and final (I would)
private final int x, y, width, height;
Alternative, for a quick hack:
int x, y, width, height;
You are also trying to call a 0-argument constructor on your println line. Your class doesn't have a 0-argument constructor; it has a 4-argument constructor. I suspect (as noted above) you really want to print this.
But that wouldn't help much, on its own, unless you add an appropriate toString method to your class. E.g.:
public String toString() {
StringBuilder sb = new StringBuilder("Rectangle: ");
sb.append("x=").append(x);
sb.append(", y=").append(y);
sb.append(", width=").append(width);
sb.append(", height=").append(height);
return sb.toString();
}
You might want to think about implementing equals() and hashCode() too, if you choose to make this class immutable (I would). You can ixquick* or duckduckgo* this - there are plenty of explanations around.
[*] They are search engines: I don't use google.