Lesson 16 - Gas Mileage - Multiple Classes Project - java

~~~Update: Solved! Thanks everyone!~~~
I'm working on a project from the Blue Pelican Java book, lesson 16 project Gas Mileage. It asks to create two classes, one is Automobile which holds the methods I will work with. The other class, Tester, is the main class. Every time I run the Tester class, it returns a value of -Infinity. I can't figure out why, other than that I've singled out the problem is in the Automobile class at line 14 in the takeTrip method. When I leave that method out of the Tester class, it returns the correct values.
This is the Automobile class:
public class Automobile
{
public Automobile(double m) // Accepts value m to the double mpg. Also declares
{
double mpg = m;
double gallons;
}
public void fillUp(double f) // Adds fuel to the tank
{
gallons += f;
}
public void takeTrip(double t) // Takes away fuel from the tank depending upon how many miles are driven
{
gallons -= t / mpg; // Not sure how to do this line. For some reason, when I reference mpg, the output of Tester is "-infinity". Shouldn't it do gallons = gallons - (miles driven / mpg)?
}
public double reportFuel() // Returns value of how much fuel is left in tank
{
double r = gallons;
return r;
}
public double mpg;
public double gallons;
}
And this is the Tester class:
public class Tester
{
public static void main(String args[])
{
Automobile myBmw = new Automobile(24); // Passes constructor argument of 24 mpg
myBmw.fillUp(20); // Adds 20 gallons to fillUp method
myBmw.takeTrip(100); // Takes away the fuel used for 100 miles using the takeTrip method
double fuel_left = myBmw.reportFuel(); // Initializes fuel_left to the method reportFuel
System.out.println(fuel_left);
}
}
Any help is appreciated, thanks!
-AJ

You constructor doesn't need the 'double' identifier. Here you are creating a new variable also called mpg, which is forgotten after the constructor completes. Instead use this:
public Automobile(double m) // Accepts value m to the double mpg. Also declares
{
mpg = m;
}

This is the problem:
public Automobile(double m) // Accepts value m to the double mpg. Also declares
{
double mpg = m;
double gallons;
}
This is declaring a local variable called mpg, rather than changing the value of the instance variable for the object. (The instance variables are declared at the bottom of the class.) It's then declaring another local variable called gallons which isn't assigned any value. At the end of the constructor, the instance variables gallons and mpg will both be zero - which means you'll be dividing by zero in the takeTrip method - so you're subtracting "infinity gallons" from the fuel tank, leading to your final result. Your constructor should look like this instead:
public Automobile(double m)
{
this.mpg = m;
}
or just:
public Automobile(double m)
{
mpg = m;
}
If you're still unsure about local variables and instance variables after this, see if there's anything earlier in the book which might help you. (By lesson 16 I'd expect it to have been covered...)

In your Automobile c'tor, you're currently creating a local variable called mpg, instead of changing the class member. All there should be in that function is mpg = m; (the second line does nothing).
Currently, mpg (the member) is automatically initialized to 0, and then t/mpg is infinity, and when you take that away from some finite number, you get -infinity.
By the way, in reportFuel(), you could just as well just write return gallons;, without declaring r.

public class Automobile {
private double mpg = 0; //need to handle the division by 0 if you
//initialize it to 0
private double gallons = 0;
public Automobile(double m, double g)
{
mpg = m;
gallons = g;
}

Why are again declaring your attributes inside your constructor where as you have already declared them in your class. Actually the attributes you are declaring inside the constructor will not persist after the execution of the method ends (in this case the constructor). So though you are trying to initialize the attributes of your class you are actually not doing this.
So in your constructor try this
mpg=m
gallons=0
I think the other methods are fine. Another thing try to keep those attributes (mpg and gallons) private. Though the program will run without any error still you are violating the main thing of oop - encapsulation. cheers :)

Related

Why am I getting the error "cannot resolve method "x" in "x""?

The purpose of this program is to create a class and tester class for a select object(in my case a monitor), with at least one overloaded method. And in the client class, I have to instantiate at least three instances of the object. So far I believe I've finished the first class with the declaration of methods, getters and setters, and constructors. The problem occurs in my tester class, where I get the error "Cannot resolve method 'MonitorV82' in 'Monitor V82'. I don't know for sure why I'm getting this error, any advice?
My first class is:
public class MonitorV82
{
private double l;
private double h;
//one parameter constructor, all private instance variables initialized
public MonitorV82(double monitor1Height) {
//2.When this gets name1(jupiter), it designates "jupiter" to the variable "n"
h = monitor1Height;
l = (monitor1Height * 1.77);
}
//two parameter constructor
public MonitorV82(double monitor1Height, double monitor1Length){
//3.When this gets name1(jupiter), and a double, it sets jupiter to "n" and the diameter to "d"
h = monitor1Height;
l = monitor1Length;
}
public double getMon1height() { return h; }
public double getMon1Length() {
return l;
}
public void setMon1height(double name) { h = name; }
public void setMon1Length(double diam) {
l = diam;
}
public String monType(int resolution)
{
String monitType = "";
if (resolution == 1080) {
monitType = "lenovo";
} else if (resolution == 4000) {
monitType = "samsung";
}
return monitType;
}
//overloaded method
public String monType(int pixLength,int pixHeight)
{
String monitType = "";
if (pixHeight == 1080) {
monitType = "lenovo";
} else if (pixHeight == 4000) {
monitType = "samsung";
}
return monitType;
}
}
My tester class(where the error is) is:
public class V8Tester {
public static void main(String[] args) {
double length1 = 32.2;
double height1 = 51.8;
double length2 = 31.8;
double height2 = 50.6;
int resolution = 0;
MonitorV82 monit1 = new MonitorV82(length1);
resolution = monit1.MonitorV82(height1);
}
}
I am still learning Java in school so please don't roast me if something seems obvious or simple. Thank you for your help.
You are getting this error because there is no method MonitorV82, only a constructor. Also you are trying to instantiate the int variable resolution with a MonitorV82 object, which is not possible, because the compiler expects an int value.
If you want the resolution that refers to the pixel count of the MonitorV82 object with known pixel height, you first need to find out it's pixel length. You can do this by using your getMon1length() method and the calculate the resolution by length * height. Ultimately what I think you are trying to do is:
int heightMonit1 = monit1.getMon1height();
int resolution = (int)length1 * (int)heightMonit1;
You need to type cast, because you want to instantiate the int variable resolution with a calculation of double values.
You could however also use your second constructor and do:
MonitorV82 monit1 = new MonitorV82(length1, height1);
int resolution = (int)monit1.getMon1height() * (int)monit1.getMon1length();
Before answering the question in the title, you need the answer to this question:
What is a constructor in Java?
A constructor in Java is a special method used to "construct" (build, instantiate, etc.) objects. A constructor follows these basic rules:
The name of the constructor should match exactly the class name. In your case, MonitorV82 is this name.
A constructor doesn't have a return type. The new operator is responsible for returning a new object matching the type of the class in which the constructor is being invoked.
Knowing this, let's address the original question: Why the error? Because in MonitorV82 there is only a constructor a with matching name, but not a regular method with the same name. Consider my example below
public class Test {
private String name = "default";
// constructor #1
public Test() {}
// constructor #2
public Test(String name) {
this.name = name;
}
// method #1
public void Test() {
System.out.println(name);
}
// method #2
public void Test(String name) {
System.out.println(name);
}
}
Notice that in the code above, I have two constructors and two methods with the same name (matching case) and same parameters. This is allowed in Java although this is STRONGLY discouraged due to how confusing it can get.
What does this mean for you?
To create monit1, you need to invoke a CONSTRUCTOR. Once you construct the object, you cannot use it to invoke a constructor. You use objects to invoke non-static, accessible methods. Based on this, the line
MonitorV82 monit1 = new MonitorV82(length1);
is totally fine. However, the set resolution line is not resolution = monit1.MonitorV82(height1); because you have no METHOD named MonitorV82 (you just have a constructor with a matching name). You fix this by creating a method in your class that does exactly that. Since method names should be descriptive of their function, creating a method named setResolution or calculateResolution should be fine. What you should not do is used an ambiguous name; especially using the same name as the constructor.
Lastly, I will leave you with this small piece of advice: Just because the language allows you to do something, that does not mean that it is correct or OK to do so. My code example (along with this lengthy explanation) should've illustrated this point.
tl;dr
You asked:
Why am I getting the error "cannot resolve method "x" in "x""?
Because your last line tries to call a method named MethodV82 which does not exist on an instance of the class named MethodV82.
Details
Firstly, you should have indicated which line of code is causing that error.
You have at least one offending line, that last line. The code monit1.MonitorV82(height1) makes no sense. That code is trying to call a method named MonitorV82 on the instance named monit1. But of course there is no such method. Thus the error « Cannot resolve method ».
I cannot follow your logic, so I cannot give a fixed replacement code snippet.
I think you are misunderstanding the use of constructors.
I guess that what you want to do with your monit1.MonitorV82(height1) is to set the height of your monit1 instance to height1.
You need to call the setter to do so, not a constructor. The constructor is not known as a class method, that is why your error occurs. Use
monit1.setMon1height(height1);
Next, I think that you are trying to retrieve a resolution from your monitor, but you have no method inside of your MonitorV82 with this aim so I suggest that you create a method for this such as
public int computeResolution() {
return this.h * this.l;
}
In your test class you end up with:
public class V8Tester {
public static void main(String[] args) {
double length1 = 32.2;
double height1 = 51.8;
double length2 = 31.8;
double height2 = 50.6;
int resolution = 0;
MonitorV82 monit1 = new MonitorV82(length1);
monit1.setMon1height(height1);
resolution = monit1.computeResolution();
}
}
Edit: Even the instantiation of your monit1 does not seem correct. The only one parameter constructor you have is based on height and you are calling it with length1
Edit2: My example of computeResolution() will probably end up with an exception as I am returning an int from a compute action on doubles. But I think that it is not the main issue here

Using 2 classes for a Comission Calculator in Java

I am doing an assignment for a beginning Java class. We have to write a commission calculator and use two classes in it. I am stuck on how to use variables from one class in a second class. The methods that i have found so far are not working for me. Any advice would be greatly helpful. Below is the code i have so far.
package calc;
/**
*
* #author Ethan
*/
import java.util.Scanner;
public class Calc {
public static void main(String[] args) {
Scanner calcu = new Scanner(System.in); //Creats the scanner used for Input
//Sets all of the variables to be used
double sal; //salary
double com1; //Comission percentage
double com2; // Find the ammount of comisssion from yearly sales
double comp; //Yearly Sales
double frac; //Decimal Comission form
double total; // Total of Compensation of Yearly salary + Comission
System.out.println("Enter the annual Salary here: ");
sal = calcu.nextDouble();
System.out.println("Enter the total Sales here: ");
comp = calcu.nextDouble();
Rate();
frac = com1/100; //converts the Sales Comission to a decimal
com2 = frac * comp; // Find the total Comission based on the
total = sal + com2; //find the total compensation
System.out.print("Your total compensation is " + total);
}
private static void Rate(){
// Rate of commission is determined below.
if (comp < 10000)
com1 = 20; //20% commission rate
else if (comp < 30000)
com1 = 22; // 22% commission rate
else if (comp < 50000)
com1 = 23; // 23% commission rate
else if (comp < 100000)
com1 = 24; // 24% commission rate
else
com1 = 25; // 25% commission rate
}
}
The problem i have is the i can't pull the rates so they can be used in the calculations.
A few major issues on your code. Your code is encapsulated in the Calc class, but no constructor is ever called. (eg. new Calc()). Rate() is a method in Calc, so it would be called by Calc.Rate(). Check out a few more examples of how to construct a java class, and you will understand encapsulation of your variables.
You only have posted one class so far. Where is the second? You will need to make sure both classes are in separate files as well.
public class Class1(){
//Class variables
public int myPublicInt; //public variables are accessable to any class that calls it
private int myPrivateInt; //private variables can not be modified outside of the class
//Class constructor, this is used to create objects of a class
public Class1(){
myPublicInt = 0;
myPrivateInt = 1;
}
//Now we have setter and getter methods to handle private variables
public void setMyPrivateInt(int newValue){
myPrivateInt = newValue;
}
public void getMyPrivateInt(){
return myPrivateInt;
}
//lastly this is a private method, only Class1 objects can call this method
//internally, so we can call it in our constructor but not from Class2
private void somePrivateMethod(){
//does something
}
}
So Now you will have some first class, it has some data and some methods and a constructor. Making variables public is not a good idea for the security of your code, you will want to make your second program create an object of the first one to access its variables and method calls. See the below program.
public class Class2{
//Class Variables, declares an object of the first class
private Class1 myClassObject;
//Constructor for this class, instantiates the first class object
public Class2(){
myClassObject = new Class1();
}
//Main method and runtime of our program
public static void main(String args[]){
Class2 thisClass = new Class2();
thisClass.printMyPrivateIntFromClass1();
}
//Method from this class, Class2
public void printMyPrivateIntFromClass1(){
System.out.println(myClassObject.getMyPrivateInt());
}
}
So in the second class we make an object of the first one, this way we can manipulate and use that object, its data and its methods. Notice that I used constructors to make objects of each class. When you call that object you can also call its public methods and variables. Again I would not recommend making variables public because then they are too easy to manipulate. If you have public methods that lead to your variables you can use those as a safer way to change or access the data stored in them. Hope this helps explain using a class inside another.
A couple of other notes, work on indentation, you should use the same indentation for code nested on the same level, and anything nested underneath something else by use of {} should be indented in once more so that code is more readable for you and others.

How to build a "Circle" object that lets the user determine the radius?

I'm taking an object oriented programming class and I'm having some difficulty understanding how to build a circle object that lets the user declare what the radius is.
I created a data class and in it I put my instance variable, my getter and setter methods, my constructor, and then the basic computational function methods to compute the area and perimeter of the circle with a given radius.
Here is that class:
package shapesoo;
public class CircleDataClass {
private double radius;
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
public CircleDataClass(double radius) {
this.radius = radius;
}
public double getArea(){
return Math.PI * radius * radius;
}
public double getCircumference(){
return 2 * Math.PI * radius;
}
}
Then, I am creating a test class that builds the circle with the given radius and in my main method I create the new circle object with:
CircleDataClass myCircle = new CircleDataClass(radius);
I don't have radius declared anywhere in this test class so that's why I am getting a run-time error. But what I want is a user to input the value for that radius parameter that I have in my constructor and then have that radius passed to this circle object. Do I create a separate method in my main class that asks for the value of the radius? I think I am getting confused with what getters/setters/cosntructors are doing and how to pass the radius variable around to different classes.
EDIT: If I put this in, is the instance variable from my data class even used?
public static void main(String[] args) {
String shapeType = getShape();
if (shapeType.equalsIgnoreCase("Circle")){
String r = JOptionPane.showInputDialog("What is the radius: ");
double radius = Double.parseDouble(r);
CircleDataClass myCircle = new CircleDataClass(radius);
}
}
I know how to do this without using object-oriented principles and I am aware this must seem elementary to many of you but I would appreciate any help on it.
I don't have radius declared anywhere in this test class so that's why I am getting a run-time error.
Ok, that's normal
But what I want is a user to input the value for that radius parameter that I have in my constructor and then have that radius passed to this circle object. Do I create a separate method in my main class that asks for the value of the radius?
Yes. Basically, you can read the standard input for the user to enter a number and then instantiates the circle with it. See the Scanner class.
I think I am getting confused with what getters/setters/cosntructors are doing and how to pass the radius variable around to different classes.
The constructor is used to create and initialise an instance of a class.
The getter(s) gives read-only access to properties of your instance. In your case, if you want to check what is the radius of a particular instance of circle, you can have it through myCircle.getRadius().
The role of setter(s) is to mutate an instance, i.e. to change internal properties. It may not be good practice to have setters and can be better to create a new object when there is a need to change a property. This really depends on your design and context.

non-Static method toString cannot be referenced from a static context

I'm trying to create a program that reads user input and stores it and then calculates the area of a polygon. When I try and compile it it gives me one error which is the one about .toString being non static.
import java.util.Scanner;
class regularpoTest {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
boolean finished = false;
double s;
double n;
double area;
//starts loop to record data
do {
s =0;
n =0;
System.out.println("Enter the side length, or anything else to quit: ");
s = in.nextDouble();
in.nextLine();
if (in.hasNextDouble()) {
System.out.println("Enter number of sides");
n = in.nextDouble();
area = (s*s*n)/(4*Math.tan(Math.PI/n));
} else {
finished = true;
}
} while(!finished);
//This prints out the student details
System.out.println(regularpo.toString());
}
}
public class regularpo {
private double side;
private double numberOf;
private double area;
public regularpo(double side, double numberOf){
side = 0;
numberOf = 0;
area = 0;
}
public double getSide(){
return side;
}
public double getNumberOf(){
return numberOf;
}
public String toString(){
return ("area = " + area+ " side length "+side+ " number of sides "+numberOf);
}
}
You are trying to call a method of a class, when that method has been defined for (and only makes sense as) a method of an instance of that class. Maybe you mean to make an object of that class, and call its toString method, although I can't be sure from your code.
You can not access non-static methods by using classname.nonStaticMethodName. You need to instantiate your object using the new keyword. Basically, you create an instance of your object by regularpo r = new regularpo(2.0, 2.0). After that you can invoke r.toString();
Check out this SO-question for more info.
And this Oracle-tutorial explains class members well.
Suggestions:
1) Eliminate "regularpoTest". Just move "main()" into "regularpo".
2) Capitalize "RegularPo" (by convention, class names should start with a capital letter).
3) Make the RegularPo constructor actually save the initial values (not just set them to zero).
... and, most important ...
4) Your main should call RegularPo regularPo = new RegularPo (...).
Then reference object instance "regularPo".
Try to make a object of class regularpo and call toString over that object
regularpo obj=new regularpo();
obj.toString();
Also as per conventions a class name must start with Upper case,so name your class asRegularpo
toString() is a non static method in regularpro class , and we know that the non static belongs to an object so we need to create and object of same class and call it.
toString() is belongs to Object class so its non static method.
regularpo obj=new regularpo();
obj.toString();

How public members of a class causes havoc in java?

How public members of a class causes havoc in java? Can someone please explain with example? I tried to create such situation but couldn't succeed. I simply found them equivalent to 'protected' access modifier.
It allows invalid values, breaking encapsulation.
public class Clock {
public int hours;
public int minutes;
}
Then, in unrelated code...
Clock clock = new Clock();
clock.hours = 42;
clock.minutes = 99;
Having them private with setter and getter methods allows encapsulation to enforce proper values.
public class Clock {
private int hours;
private int minutes;
public void setHours(int hours) {
if (hours < 0 || hours > 23) throw new IllegalArgumentException("bad range");
this.hours = hours;
}
// Likewise for "setMinutes" method.
}
Here's a tutorial page on encapsulation in Java on encapsulation's benefits. Quoting:
The fields of a class can be made read-only or write-only.
A class can have total control over what is stored in its fields.
The users of a class do not know how the class stores its data. A
class can change the data type of a field, and users of the class do
not need to change any of their code.
I believe it all depends on the application/program that you design.
Declaring the members as private definitely does have advantages.
But on the other hand,
If you design say a Point Class, which the users would be inheriting
and using it to draw various shapes, square, rectangle, circle, you
might think of keeping the memebers x, y, z as public.
Example:
class Point{
public double x = 0.0;
public double y = 0.0;
public double z = 0.0;
}
The advantage here would be; the classes Rectangle, Square, can access the points directly
say;
class Square extends Point{
private Point p;
p.x = 4.0;
p.y = 10.0;
p.z = 0;
// Instead of using double x = p.getX(); double p.setX(5.0);
}
Hope this helps.
Read the below articles; it should help you.
Source 1
Source 2
Source 3

Categories