Object ArrayList For-Loop Error - java

I have an Object ArrayList and I need to use the toString() method of the Motor object, which is a parameter of the Vehicle object. My vehicle objects are in an ArrayList which is iterated through with a for-loop (I know a foreach loop would be easier, but this is part of the assignment)
Here is the code for the loop:
for (int i = 0; i < VehicleList.size(); i++) {
System.out.println();
String info = VehicleList.get(i).toString();
Motor m = VehicleList.get(i).motor;
String motorInfo = m.toString();
System.out.println(info);
System.out.println(m);
}
There is an error that says "motor cannot be resolved or is not a field".
All of the classes should allow this to work, unless of course there is a simple mistake I am missing.
Here is the Motor class:
public class Motor {
protected String name;
protected int cylinders;
protected int bhp;
protected double displacement;
public Motor(String name, int cylinders, int bhp, double displacement) {
this.name = name;
this.cylinders = cylinders;
this.bhp = bhp;
this.displacement = displacement;
}
public String toString() {
return "Motor name= " + name + ", cylinders= " + cylinders + ", bhp=
" + bhp + ", displacement= " + displacement;
}
}
Motors and Vehicles are intitialized here (In the TestVehicle class):
//Motors
Motor EcoBoost = new Motor("EcoBoost", 6, 310, 2.3);
Motor Hemi = new Motor("Hemi", 8, 707, 5.7);
Motor P90D = new Motor("P90D", 0, 762, 0.0);
//Vehicles
Vehicle v0 = new PassCar("Ford", "Mustang", 2016, 44500.0, 5, true, EcoBoost);
Vehicle v1 = new PassCar("Tesla", "Model S", 2016, 121000.0, 2, true, P90D);
Vehicle v2= new Truck("Dodge", "Ram", 2016, 46000.0, "pickup", 1500, Hemi);
PassCar and Truck are inherited classes of Vehicle with a few more attributes. I can post the PassCar or Truck class if needed but I do not think that is where the problem is arising from. I believe it is coming from the For-Loop, specifically the line Motor m = VehicleList.get(i).motor; but I am not sure of how to fix it.
Vehicle Class:
public class Vehicle {
protected String make;
protected String model;
protected int year;
protected double price;
public Vehicle(String make, String model, int year, double price) {
this.make = make;
this.model = model;
this.year = year;
this.price = price;
}
public void description() {
System.out.println("Description");
}
public String toString() {
return "make= " + make + ", model= " + model + ", year= " + year +
", price= " + price;
}
}
EDIT: There cannot be any Getters or Setters as per the assignment requirements, and it must be an ArrayList, not a regular List. When I switch to I get the error "Type mismatch: cannot convert from ArrayList to ArrayList
Here is an image of the classes:

ArrayList<Object> VehicleList = new ArrayList<>(Arrays.asList(vehicles));
VehicleList is declared to contain instances of Object, so the compiler will only let you access methods and fields it knows exist on all instances of Object.
Change it to ArrayList<Vehicle>.

First, mind the naming convention. Variables should be named in camcelCase e.g. vehicleListinstead ofVehicleList`
I have an Object ArrayList
I believe you mean declaration of vehicleList looks like ArrayList<Object> vehicleList
Then behavior is expected because compiler only knows that VehicleList.get(i) is going to return you an Object reference. It can be a Vehicle, but it can also be anything else. So it won't allow you to access the motor field, as there is simply no such field in Object.
Change your declaration to something like List<Vehicle> vehicleList
However, as mentioned in other answer, it is not a good idea to access the field directly because of various reason. A slightly less evil way is to have getter of motor. (A better way is to provide meaningful behaviors instead of providing access to internal data)

Create an interface IMotor which is used by Vehicle class and Implemented in PassCar and other implementation of vehicle.
IMotor.java
public interface IMotor {
public Motor getMotor();
}
Motor.java
public class Motor {
protected String name;
protected int cylinders;
protected int bhp;
protected double displacement;
public Motor(String name, int cylinders, int bhp, double displacement) {
this.name = name;
this.cylinders = cylinders;
this.bhp = bhp;
this.displacement = displacement;
}
public String toString() {
return "Motor name= " + name + ", cylinders= " + cylinders + ", bhp=" + bhp + ", displacement= " + displacement;
}
}
Vehicle.java
public abstract class Vehicle implements IMotor{
protected String make;
protected String model;
protected int year;
protected double price;
public Vehicle(String make, String model, int year, double price) {
this.make = make;
this.model = model;
this.year = year;
this.price = price;
}
public String toString() {
return "make= " + make + ", model= " + model + ", year= " + year +
", price= " + price;
}
}
PassCar
public class PassCar extends Vehicle{
protected Motor motor;
public PassCar(String make, String model, int year, double price, Motor motor) {
super(make, model, year, price);
this.motor = motor;
}
public Motor getMotor() {
return motor;
}
}
Test.java
import java.util.Arrays;
import java.util.List;
public class Test {
public static void main(String[] args) {
Motor EcoBoost = new Motor("EcoBoost", 6, 310, 2.3);
Vehicle v0 = new PassCar("Ford", "Mustang", 2016, 44500.0, EcoBoost);
List<Vehicle> vehicles = Arrays.asList(v0);
System.out.println(vehicles.get(0).getMotor());
}
}

Your problem is that motor is not a member of the Vehicle class, but you are trying to access it through an expression of type Vehicle - namely vehicleList.get(i). This is forbidden, because the compiler has no way of knowing that every possible kind of Vehicle has a motor. After all, what would happen if you added a Bicycle class?
To make this work, you should remove motor from the Truck and PassCar classes, and add it to the Vehicle class. That way, vehicleList.get(i).motor would actually make sense, since the Vehicle expression would be guaranteed to refer to a Vehicle with a Motor.
It would also be recommended to use a getter for the motor field - that is, have motor as a private field of the Vehicle class, and write a method getMotor() to return it. You could then write vehicleList.get(i).getMotor() to get the Motor object associated with one Vehicle in the list.

Thanks to the help of all of your comments and my Java textbook, I managed to piece it together. Here is how I got it to work:
for (int i = 0; i < vehicleList.size(); i++) {
String motorInfo = "";
String info = "";
System.out.println();
if (vehicleList.get(i) instanceof PassCar) {
info = ((PassCar)vehicleList.get(i)).toString();
**motorInfo = ((PassCar)vehicleList.get(i)).motor.toString();**
}
else if(vehicleList.get(i) instanceof Truck) {
info = ((Truck)vehicleList.get(i)).toString();
**motorInfo = ((Truck)vehicleList.get(i)).motor.toString();**
}
Basically I had to use a polymorphic call and check if it was an instance of a PassCar or Truck.
And as for the Array and ArrayList used during the Class, I edited them like this:
Vehicle [] vehicles = new Vehicle [3];
vehicles[0] = v0;
vehicles[1] = v1;
vehicles[2] = v2;
showVehicle(vehicles);
ArrayList<Vehicle> vehicleList = new ArrayList<Vehicle>(Arrays.asList(vehicles));
System.out.println();
System.out.println("Output from ArrayList in main: ");
Thank you for the help everyone!

Related

Passing instances created in main to classes in Java

I'm stuck with one of the final drills in my java programming course and would appreciate a pointer as to what I should be doing to satisfy the outcomes required.
The code will be tested by the following code which can't be altered:
Test:
int wheels = 4;
String make = "Honda";
String color = "Yellow";
Vehicle v1 = new Vehicle(make);
System.out.println(v1.aboutMe());
Vehicle v2 = new Vehicle(make, color);
System.out.println(v2.aboutMe());
Vehicle v3 = new Vehicle(make, color, wheels);
System.out.println(v3.aboutMe());
Result:
Vehicle object created.
Make: Honda
Colour: Blue
Wheels: 4
Vehicle object created.
Make: Honda
Colour: Yellow
Wheels: 4
Vehicle object created.
Make: Honda
Colour: Yellow
Wheels: 4
The code I have written is here but doesn't compile (temporary solution is greyed out but doesn't meet testing criteria as alters main method to passes parameters from the instance):
public class Vehicle {
// TODO your code goes here
// declare instance fields here!
String make;
String color;
int wheels;
public String aboutMe() {
String statement = "Make: " + make + "\n" + "Colour: " + color + "\n" + "Wheels: " + wheels;
return statement;
}
// constructor method
public Vehicle(String vehicleMake, String vehicleColor, int vehicleWheels) {
make = vehicleMake;
color = vehicleColor;
wheels = vehicleWheels;
}
//Test:
public static void main(String[] args) {
int wheels = 4;
String make = "Honda";
String color = "Yellow";
System.out.println("Vehicle object created.");
//CODE REQUIRED BY TEST:
Vehicle v1 = new Vehicle(make);
//Vehicle vh1 = new Vehicle("Honda", "Blue", 4);
System.out.println(vh1.aboutMe());
//CODE REQUIRED BY TEST:
Vehicle v2 = new Vehicle(make, color);
//Vehicle vh2 = new Vehicle("Honda", "Yellow", 4);
System.out.println(vh2.aboutMe());
//CODE REQUIRED BY TEST:
Vehicle v3 = new Vehicle(make, color, wheels);
//Vehicle vh3 = new Vehicle("Honda", "Yellow", 4);
System.out.println(vh3.aboutMe());
}
//Code stops here
}
In summary, how do I pass the instances declared in the main to the constructor?
Thanks kindly, this is my first post on here so much appreciated for bearing with me while I learn the correct protocol for asking questions on here.
Edit: thanks kindly the code runs now much appreciated
public class Vehicle {
// TODO your code goes here
// declare instance fields here!
String make;
String color;
int wheels;
public String aboutMe() {
String statement = "Vehicle object created.\n" + " Make: " + make + "\n" + " Colour: " + color + "\n" + " Wheels: " + wheels;
return statement;
}
//constructor method
public Vehicle(String vehicleMake, String vehicleColor, int vehicleWheels) {
make = vehicleMake;
color = vehicleColor;
wheels = vehicleWheels;
}
public Vehicle(String make) {
this(make, "Blue");
}
public Vehicle(String make, String color) {
this(make, color, 4);
}
public static void main(String[] args) {
int wheels = 4;
String make = "Honda";
String color = "Yellow";
//System.out.println("Vehicle object created.");
Vehicle v1 = new Vehicle(make);
System.out.println(v1.aboutMe());
Vehicle v2 = new Vehicle(make, color);
System.out.println(v2.aboutMe());
Vehicle v3 = new Vehicle(make, color, wheels);
System.out.println(v3.aboutMe());
}
// Code stops here
}
You need to create other constructors
public Vehicle(String make) {
this(make, "Blue");
}
public Vehicle(String make, String color) {
this(make, color, 4);
}

Implementing a Demo/Tester Program

I have a project for my java programming course.
The instructions are that we have to create a simple class and a tester class, and the class must include a Default constructor; Parameterized constructor with three parameters (make, model and price); Accessor method called getMake( ) to return the make; Accessor method called getModel( ) to return the model; Accessor method called getPrice( ) to return the price; Mutator method setMake( String newMake) to set the make; Mutator method setModel( String newModel) to set the model; and a Mutator method setPrice( double newPrice ) to set the price..
I have created my class and tester program, and my class compiles perfectly. When I try to run it, though get the error that there is no main method. Now, I followed my professor's example for the tester program and I get several errors on that. If anyone could give me the a pointer in the right direction, I would appreciate it.
My question is this: How do I implement my tester program? Do I need to create a zip file? I've tried doing so and didn't seem to help much...
The following is my code for the class:
public class Automobile
{
private String make;
private String model;
private double price;
public Automobile()
{
make = "Lexus2017";
model = "RX";
}
public Automobile(String initMake, String initModel, double initPrice)
{
make = initMake;
model = initModel;
price = initPrice;
}
public String getMake()
{
return make;
}
public String getModel()
{
return model;
}
public double getPrice()
{
return price;
}
public void setMake(String newMake)
{
make = newMake;
}
public void setModel(String newModel)
{
model = newModel;
}
Also, the following is my tester class(the one that has a lot of errors):
public class AutomobileTester
{
public static void main(String[] args)
{
Automobile make = new Automobile("Lexus 2017");
System.out.println("The car is " + make.getMake());
Automobile model = new Automobile("RX");
System.out.println("The car is " + Automobile.getModel());
Automobile price = new Automobile("43020");
System.out.println("The car is " + Automobile.getPrice());
// Use the mutator to change the make variable
Automobile.setMake("Lexus 2017");
System.out.println("The car is " + backDoor.getState());
// Use the mutator to change the model variable
Automobile.setModel("RX");
System.out.println("The car is called " + backDoor.getName());
Automobile.setPrice("43020");
System.out.println("The car is " + price.getPrice());
}
}
This is my first time working with constructors, and I'm very new to Java, so I'm sorry for any obvious errors. Thank you ahead of time for your time and help.
One of the first problems is that you do not use the proper number of parameters for your calls to the constructor, in Java (and most programming languages) you have to supply all of the required parameters to a method/function/constructor in one call. The fix for your code would be to use:
Automobile car = new Automobile("Lexus 2017", "RX", 43020.0D);
Also when you print out the cars information you first use an instance call then you use a static call, I won't go to much into the difference between the two but basically an instance call requires you to instantiate an object while a static does not. The fix for this problem would be to do:
System.out.println("The car is a " + car.getMake() + ", the brand is " + car.getModel() + ", the price is $" + car.getPrice());
As for changing the variables you should be using:
car.setMake("My New Car Make");
instead of:
Automobile.setMake("My New Car Make");
For the difference between static and instance you can look here, here, and here.
You did this correctly. You accessed the method by using the make instance variable of an Automobile class.
(side note: make is a bad name for an automobile instance, rather call it car1, or something)
Automobile make = new Automobile("Lexus 2017");
System.out.println("The car is " + make.getMake());
Now, everywhere else that you use Automobile.someMethod(), that's not right, because you need to set or get the data on one instance of the class, not the entire class.
Then, finally, you need to test the constructor with three parameters that you have in that class.
You have an error in the constructor call.
Your constructor takes three parameters (make, model and price) but when you call the method only send one. That is an error.
By default, the Java class constructor takes no parameters (in your case, this would be "new Automobile ()").
To implement the tester you have two options.
First, create the car using the constructor without parameters and then set the parameters:
Automobile auto = new Automobile();
auto.setMake("Lexus 2017");
auto.setModel("RX");
auto.setPrice(43020);
Automobile Automobile make = new Automobile ();
Another option is to use your own builder and pass parameters:
Automobile auto2 = new Automobile("Lexus 2017", "RX", 43020);
Automobile.java:
public class Automobile {
private String make;
private String model;
private double price;
public Automobile() {
}
public Automobile(String make, String model, double price) {
this.make = make;
this.model = model;
this.price = price;
}
public String getMake() {
return make;
}
public void setMake(String make) {
this.make = make;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
AutomobileTester.java:
public class AutomobileTester {
public static void main(String[] args) {
Automobile auto = new Automobile();
auto.setMake("Lexus 2017");
auto.setModel("RX");
auto.setPrice(43020);
System.out.println("The car1 is " + auto.getMake() + " " + auto.getModel() + " " + auto.getPrice());
Automobile auto2 = new Automobile("Lexus 2017", "RX", 43020);
System.out.println("The car2 is " + auto2.getMake() + " " + auto2.getModel() + " " + auto2.getPrice());
}
}

What's the importance in using the set method when the attributes have already been defined in the Used Defined Constructor? [duplicate]

This question already has answers here:
Setter methods or constructors
(10 answers)
Why use getters and setters/accessors?
(37 answers)
Closed 6 years ago.
In the below code I've already declared that room = r; subject = s; and time = t; in the user defined constructor, so why is it necessary to do so again in set methods, my lecturer specifically asked that we add set methods for the room subject and time but it's redundant code as when I comment it out it still works. Do you only need to include set methods when there is no used defined constructor? What could be the advantage of having them set methods there?
class LectureTest{
public static void main (String [] args){
Lecture l1 = new Lecture(140, "Comp", 5);
l1.display();
Lecture l2 = new Lecture(280, "Sports", 3);
l2.display();
Lecture l3 = new Lecture(101, "Business", 5);
l3.display();
Lecture l4 = new Lecture(360, "Shooting", 4);
l4.display();
Lecture l5 = new Lecture();
l5.display();
}
}//end of LectureTest
class Lecture{
private int room;
private String subject;
private int time;
Lecture(int r, String s, int t){
room = r;
subject = s;
time = t;
}
Lecture(){}
public void setroomNumber(int r){
room = r;
}
public void setSubject(String s){
subject = s;
}
public void setTime(int t){
time = t;
}
public int getroomNumber(){
return room;
}
public String getSubject(){
return subject;
}
public int getTime(){
return time;
}
public void display(){
System.out.printf("\n" + "Room Number: " + getroomNumber() + "\n" + "Subject: " + getSubject() + "\n" + "Time " + getTime() + "\n");
}
}
The constructor "initializes" your values.
Let's say you have...
public class Person {
public String name;
public int age;
public Person (String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String toString() {
String str;
str = "My name is "+name+" and I am "+age+" years old!";
return str;
}
}//End of Person
public class Main {
public static void main(String [] args) {
Person person = new Person("Bob", 15);
System.out.println(person.toString());
System.out.println("Switching my name...");
person.setName("Joe");
System.out.println(person.toString());
}
}//End of main
You see the difference? You should use the constructor if you want to create a new instance of the object. This way, you can set all the fields of the object at once and not need to call 490832490 setters (in this case, one for name and one for age...). You then can use the setter approach when you want to change the value of a field, PRIOR TO the object been created.
I DID ALL THIS ON THIS FORUM SO I MIGHT HAVE SYNTAX ERRORS SO CAREFUL...DIDN'T USE AN IDE IF YOU WANT TO TEST IT
The set methods make your object mutable. If you don't have the set methods and your variables are private then the Object will be immutable. You won't be able to change the values after it is constructed...If the values need to change you would have to create a new Object.
"Setters" allow you to modify private attributes of your object after instantiating. For example:
Lecture l1 = new Lecture(140, "Comp", 5);
//Since "room" is private you can't write l1.room = 4
//and have to use the setter method instead:
l1.setroomNumber(4);
l1.display();
They are also very useful if you want to do something if an attribute changes.
Let's assume you are using Observers, then you could call notifyObservers() or setChanged() in your setter method and never have to worry about these methods not getting called if your attribute changes.

Passing to Setter and Getter methods

I have a Bread class and a Filling class which set the bread type and calories per slice as well as a filling class which sets the filling type and calories per serving... I can't seem to figure out how to pass them into the sandwich class correctly. My total calories doesn't work out
private class Sandwich {
private Bread bread;
private Filling filling;
private Bread caloriesPerSlice;
private Filling caloriesPerServing;
private Sandwich(String breadType, int caloriesPerSlice, String fillingType, int caloriesPerServing) {
setBread(bread);
setBread(caloriesPerSlice);
setFilling(caloriesPerServing);
setFilling(filling);
}
public Bread getBread() {
return bread;
}
public void setBread(Bread bread) {
this.bread = bread;
}
public Filling getFilling() {
return filling;
}
public void setFilling(Filling filling) {
this.filling = filling;
}
public int getTotalCalories(int caloriesPerSlice,int caloriesPerServing) {
(caloriesPerSlice) * 2 + caloriesPerServing = totalCalories;
return this.totalCalories;
}
}
You have your variable assignment backwards.
(caloriesPerSlice) * 2 + caloriesPerServing = totalCalories; is not valid. The variable being assigned to must be on the left.
Try:
totalCalories = (caloriesPerSlice) * 2 + caloriesPerServing;
(caloriesPerSlice) * 2 + caloriesPerServing = totalCalories; Doesn't do what you think it does.
Perhaps you mean
totalCalories = (caloriesPerSlice) * 2 + caloriesPerServing;
I see some problems in your code:
why does an instance of Sandwich should have two Bread object within? A sandwich is usually made by one type of bread.
the caloriesPerSlice and caloriesPerServing should be respectively attributes of Bread and Filling.
you can't pass a String parameter to setFilling(Filling filling) method.
(caloriesPerSlice) * 2 + caloriesPerServing is not a valid left-value and is not a valid expression because caloriesPerSlice and caloriesPerServing are objects.
This is a really basic implementation of your idea:
Bread.java
public class Bread
{
private String type;
private int caloriesPerSlice;
public Bread(String type, int caloriesPerSlice)
{
this.type = type;
this.caloriesPerSlice = caloriesPerSlice;
}
public String getType() { return type;}
public int getCaloriesPerSlice() { return caloriesPerSlice; }
public String toString()
{
return type + " (" + caloriesPerSlice + "cal)";
}
}
Filling.java
public class Filling
{
private String name;
private int caloriesPerServing;
public Filling(String name, int caloriesPerSlice)
{
this.name = name;
this.caloriesPerServing = caloriesPerSlice;
}
public String getName() { return name;}
public int getCaloriesPerServing() { return caloriesPerServing; }
public String toString()
{
return name + " (" + caloriesPerServing + "cal)";
}
}
Sandwich.java
public class Sandwich
{
private Bread bread;
private Filling filling;
public Sandwich(Bread bread, Filling filling)
{
this.bread = bread;
this.filling = filling;
}
public int getTotalCalories()
{
return 2 * bread.getCaloriesPerSlice() + filling.getCaloriesPerServing();
}
public String toString()
{
return "Bread: " + bread.toString() + "\nFilling: " + filling.toString();
}
}
Main.java
public class Main
{
public static void main(String args[])
{
Bread bread = new Bread("Baguette", 150);
System.out.println("I would like a " + bread.toString());
Filling filling = new Filling("Prosciutto di Parma", 75);
System.out.println("with " + filling.toString());
Sandwich sandwich = new Sandwich(bread, filling);
System.out.println("Your order is:");
System.out.println(sandwich.toString());
int totalCalories = sandwich.getTotalCalories();
System.out.println("The total calories are " + totalCalories);
}
}
This is the output:
I would like a Baguette (150cal)
with Prosciutto di Parma (75cal)
Your order is:
Bread: Baguette (150cal)
Filling: Prosciutto di Parma (75cal)
The total calories are 375
The class has a lot of errors:
You have a Bread caloriesPerSlice, but the constructor uses the same variable as int.
The same with the Filling caloriesPerServing and the int caloriesPerServing.
It has a private constructor. This constructor specify that the only way you can access a class of this type is through a static method in the class that returns an Sandwich object (like with the singleton pattern), which is not the case here.
The class is private: maybe I'm wrong, but a private class in java means that no one can access it.
The constructor: for example, breadType is a string object, and it's not used. You are trying to setBread with the private variable... what is that?
The constructor: caloriesPerSlice is an int type and you use it in the setBread() setter which receives a Bread type. You are mixing types.
The same with caloriesPerServing which is used in setFilling(), which receives a Filling object....
getTotalCalories: the assignment goes on the right, not the left.
I think you have a misunderstanding of OO. For example, let's see the Bread class:
If the bread class has the properties caloriesPerSlice and breadType they maybe are part of the bread type. Let's change the class to reflect those properties:
public class Bread {
private int caloriesPerSlice;
private String type;
public Bread(String type, int caloriesPerSlice)
{
this.type = type;
this.caloriesPerSlice = caloriesPerSlice;
}
public int getCaloriesPerSlice()
{
return this.caloriesPerSlice;
}
public String getType()
{
return this.type;
}
}
Here in this case the Bread is completely defined though his constructor. You can see that the class has no setter. That's because I decided it, but it's up to you if you want a parameterless constructor and setters in the class. Here in this case I only defined getters. Let's see the Filling class:
public class Filling {
private int caloriesPerServing;
private String type;
public Filling(String type, int caloriesPerServing) {
this.caloriesPerServing = caloriesPerServing;
}
public int getCaloriesPerServing()
{
return hits.caloriesPerServing;
}
public void setCaloriesPerServing(int calories)
{
this.caloriesPerServing = calories;
}
public String getType()
{
return this.type;
}
public void setType(String type)
{
this.type = type;
}
}
Here the Filling class has getters and setters. It's just for explanation purposes: in the Filling class you can set the properties through constructor or through the setters, whilst in the Bread you can only define the properties through the constructor.
Now the Sandwich maybe can receive all the properties that define a bread and a filling (like in your case), or maybe it can receive a bread and a filling). Let's see the first case:
public class Sandwich {
private Bread bread;
private Filling filling;
public Sandwich(String breadType, int caloriesPerSlice, String fillingType, int caloriesPerServing) {
this.bread = new Bread(breadType, caloriesPerSlice);
this.filling = new Filling(fillingType, caloriesPerServing);
}
public Bread getBread() {
return bread;
}
public void setBread(Bread bread) {
this.bread = bread;
}
public int getTotalCalories() {
return this.bread.getCaloriesPerSlice() * 2 + this.filling.getCaloriesPerServing();
}
}
As you can see, we received in the Sandwich constructor all the parameters which define a bread and a filling. Then, we created the Bread and Filling objects, passing their parameters. Finally, the getTotalCalories is nothing but a simple math of the bread and filling properties.
This code was just writen in a text editor. I did not checked if it's ok or not.
In this example, Sandwich becomes a class and a factory, a very important component of the class. As you can see, the construction of the Bread and Filling classes is made through the Sandwich. It has the advantage that the Sandwich controls the creation of objects, but the thing is: Is the sandwich responsible of that? Maybe not, because when you make a sandwich in your home you get the bread and the other ingredients and you just put them on the slices... the sandwich is not responsible of the creation of a bread slice... it does not make sense in the real life. Then, maybe it's a good idea to remove the object creation in the Sandwich constructor:
public Sandwich(Bread bread, Filling filling) {
this.bread = bread;
this.filling = filling
}
This case is more 'correct' because you're making a sandwich with the elements already generated in memory. It's the same when you make a sandwich in your home: you get the bread, the filling and then you make a sandwich.
I hope this can clarify a little more about OO.
Greetings!

Java String toString method null error

Please I am trying to get the items of an order, the items are coffee muffin and timBits, by using the method
public String toString()
Every thing is working properly except that I do not get the items of the order I get null for them instead of the following:
Muffin "Bran" ,3
Coffee "Latte" , 1
TimBits "Assorted" , 24
Muffin "Chocolate" , 1
Coffee "Decaf" , 2
TimBits "Chocolate" , 12
Muffin "PeanutButter" , 2
Muffin "Blueberry" , 5
the numbers above represents the quantity of each item in the order.
class Item
{
protected String description;
protected int quantity;
protected String kind;
private double cost;
public double getCost()
{
return this.cost;
}
public Item (String description, int quantity)
{
this.description = description;
this.quantity = quantity;
}
public String toString()
{
return "Item: " + " " +kind + " " + ": description: " + " " +description +"quantity:" +" " + quantity ;
}
class Coffee extends Item
{
protected double cost1Coffee;
String kind = "Coffee";
public Coffee (String description, int quantity)
{
super(description, quantity);
cost1Coffee = 4 ;
}
}
}
class Muffin extends Item
{
protected double cost1Muffin;
protected double cost2Muffin;
protected double cost3Muffin;
String kind = "Muffin";
public Muffin (String description, int quantity)
{
super(description,quantity);
cost1Muffin = 1;
cost2Muffin = 0.75;
cost3Muffin = 0.50;
}
}
class TimBits extends Item
{
protected double cost1TimBits ;
String kind = "TimBits";
public TimBits (String description, int quantity)
{
super(description, quantity);
cost1TimBits = 0.25;
}
}
/***************************************************************/
/***************************************************************/
class A4Q1Util
{
private static ArrayList<Item> order;
private static int count = 0;
public static Item getItem()
{
Item item;
if (order==null)
{
order = new ArrayList<Item>();
order.add(new Muffin("Bran", 3));
order.add(new Coffee("Latte", 1));
order.add(new TimBits("Assorted", 24));
order.add(new Muffin("Chocolate", 1));
order.add(new Coffee("Decaf", 2));
order.add(new TimBits("Chocolate", 12));
order.add(new Muffin("PeanutButter", 2));
order.add(new Muffin("Blueberry", 5));
}
item = null;
if (count<order.size())
{
item = order.get(count);
count++;
}
{
return item;
}
}
}
output:
Item: null : description: Branquantity: 3
Item: null : description: Lattequantity: 1
Item: null : description: Assortedquantity: 24
Item: null : description: Chocolatequantity: 1
Item: null : description: Decafquantity: 2
Item: null : description: Chocolatequantity: 12
Item: null : description: PeanutButterquantity: 2
Item: null : description: Blueberryquantity: 5
Program completed normally.
Don't declare the field kind in every sub-class. Add the assignment to the constructors, e.g.:
public TimBits (String description, int quantity) {
super(description, quantity);
kind = "TimBits";
cost1TimBits = 0.25;
}
In your Item#toString method:
public String toString() {
return "Item: " + " " +kind + " " + ": description: " + " " +description +"quantity:" +" " + quantity ;
}
You use kind variable, but never initialize it through your application.
This is because you're hiding the kind field on every child class. Instead, declare it as protected in parent class and just initialize it accordingly on each child.
class Coffee extends Item {
protected double cost1Coffee;
//drop this
//String kind = "Coffee";
public Coffee(...) {
super(...);
kind = "Coffee";
}
}
You can even be more restrictive about the kind field by marking it as final and disallowing any other class modifying it except its children when executing the constructor. A sample of this:
class Item {
//other fields...
protected final String kind;
protected Item (String description, int quantity, String kind) {
this.description = description;
this.quantity = quantity;
this.kind = kind;
}
public Item (String description, int quantity) {
this(description, quantity, "uncategorized");
}
}
class Coffee extends Item {
public Coffee(String description, int quantity) {
//similar in other subclasses of Item
super(description, quantity, "Coffee");
}
}
You're assigning to String kind inside each subclass of Item. However, this kind is not the same as the kind field of the superclass Item since the subclass field masks that of the superclass. You have two options to fix this.
Expand the Item constructor to accept a String kind and add to the call to super.
super(description,quantity,"Muffin");
Assign to kind inside the subclass constructors so that the correct kind is assigned to (the one declared in Item which is used by toString()).
public Muffin (String description, int quantity)
{
kind = "Muffin";
}
It looks like you never initialize your variable kind and even though you are extending from the superclass "Item" throughout all of your child classes, you're simply overloading the variable name kind and redefining it. Therefore when you make the call to the toString() method, your parent class (Item) never gets it's kind variable initialized. What you need to do is also set the kind in the constructor so that you can pass it in through super().

Categories

Resources