I'm new in java (started 2 weeks ago) and I've been making some random challenges I found on internet. My current problem is that when I access to an override method in any of my subclasses (Tablet and Laptop), this use the arguments I give to my superclass (Device), even before I declared a new object of the class.
The code run well, doesn't have any syntax error, but clearly has a logical error, because the subclasses return the same output as the parent classes, even with different arguments, the 3 give the same output all the time. I make some test, change things, and discovered that when I call the subclasses methods, doesn't call the overwritten methods in the subclasses, always refers to the method in the parent class, and don't have the most remote idea why, the editor (I use VS Code) returns the messages with reference to the class Device, never refer to the subclasses methods.
But, when I use the method .getClass() and .getSimpleName(), refers to the subclasses, it's only with the methods that doesn't work.
The code it's:
- I pass the arguments in a class App, it's where I initialize all the code and give the arguments that are my problems:
public class App {
// It's the class that run all the code, it's suppose to run "the tests"
public static void main(String[] args) throws Exception {
Device[] devices = new Device[3];
devices[0] = new Tablet();
devices[1] = new Laptop((byte) 3, 500,'E', 250);
devices[2] = new Device((byte) 3, 600, 'D');
TotalPrice answer = new TotalPrice(devices);
answer.print_totals();
// Output I obtain:
// Total price of Devices: 700.0
// Total price of Laptops: 700.0
// Total price of Tablets: 700.0
// Output It's supposed to obtain, if the code works:
// Total price of Devices: 700.0
// Total price of Laptops: 580.0
// Total price of Tablets: 110.0
}
}
- The parent class, Device:
import java.util.HashMap;
public class Device {
// The class parent, set the values for the "devices" and calculate the cost of each
// one
static float price, basis_price = 100f;
static byte weight, basis_weight = 1;
static char consumption_w, basis_consumption_w = 'F';
Device() {
weight = basis_weight;
price = basis_price;
consumption_w = basis_consumption_w;
}
Device(byte a_weight, float a_price) {
weight = a_weight;
price = a_price;
consumption_w = basis_consumption_w;
}
Device(byte a_weight, float a_price, char a_consumption_w) {
weight = a_weight;
price = a_price;
consumption_w = a_consumption_w;
}
static float calc_consume_w() {
// Calculate the wats consumed by the device and set the cost based on this
HashMap<Character,Float> cost_w = new HashMap<Character,Float>();
cost_w.put('A', 100f); cost_w.put('B', 80f); cost_w.put('C', 60f);
cost_w.put('D', 50f); cost_w.put('E', 30f); cost_w.put('F', 10f);
return cost_w.get(Character.toUpperCase(consumption_w));
}
public float calc_price() {
// Calculates the total cost of the Device, based on initial price, weight and
// wats consumed
float cost_w = calc_consume_w(),
cost_weight = weight > 1 && weight <= 2? 10f:
weight > 2 && weight <= 3? 50f:
weight >3 && weight <= 4? 80f:
weight > 4? 100f: 0;
return price cost_w cost_weight;
}
}
- The first subclass and child of Device, Laptop:
public class Laptop extends Device {
// Same as Device, just a more specific Device
// This need the argument "Hard Disk (hd)" to add more mone to the price
static float hd, basis_hd = 250;
Laptop () {
hd = basis_hd;
}
Laptop(byte a_weight, float a_price) {
hd = basis_hd;
weight = a_weight;
price = a_price;
}
Laptop(byte a_weight, float a_price, char a_consumption_w, float a_hd) {
hd = a_hd;
weight = a_weight;
price = a_price;
consumption_w = a_consumption_w;
}
public float calc_price() {
// This it's suppose to be a overridden method for the original in Device
// Make the same thing, just that add the value for Hard Disk
float cost_w = calc_consume_w(),
cost_weight = weight > 4? 100f:
weight > 3? 80f:
weight > 2? 50f:
weight > 1? 10f: 0,
cost_hd = hd > 1000? 100f:
hd > 500? 50f:
hd > 250? 10f: 0;
return price cost_w cost_weight cost_hd;
}
}
- The second subclass and child of Device, Tablet:
public class Tablet extends Device {
// Same as Device, just add the variable ram to add more money to the price
static float ram, basis_ram = 1;
Tablet() {
ram = basis_ram;
weight = basis_weight;
}
Tablet(byte a_weight, float a_price) {
ram = basis_ram;
weight = a_weight;
price = a_price;
}
Tablet(byte a_weight, float a_price, char a_consumption_w, float a_ram) {
ram = a_ram;
weight = a_weight;
price = a_price;
consumption_w = a_consumption_w;
}
public float calc_price() {
// The supposed overridden method of Device,
// Make the same, just add more value for ram
float cost_w = calc_consume_w(),
cost_weight = weight > 4? 100:
weight > 3? 80:
weight > 2? 50:
weight > 1? 10: 0,
cost_ram = ram > 4? 50:
ram > 2? 25:
ram > 1? 5: 0;
return price cost_w cost_weight cost_ram;
}
}
- The class that performs the output, TotalPrice:
public class TotalPrice {
// This class it's the last class to be summoned, take a list of [Device, Tablets,
// Laptop], created in the class App, and calculate the total amount of the values
// of each class. It's suppose to work with n values of devices.
static float total_devices, total_laptops, total_tablets;
static Device[] devices;
TotalPrice(Device[] a_devices) {
total_devices = 0;
total_laptops = 0;
total_tablets = 0;
devices = a_devices;
}
public void print_totals() {
// This method iterate over the list of devices and add the total price of each
// one to the correspondent variable, the one that gonna be printed
for (int count = 0; count < devices.length; count) {
String name = devices[count].getClass().getSimpleName();
switch (name) {
case "Device": total_devices = devices[count].calc_price(); break;
case "Laptop": total_laptops = devices[count].calc_price(); break;
case "Tablet": total_tablets = devices[count].calc_price(); break;
}
}
System.out.println( "Total price of Devices: " total_devices "\n"
"Total price of Laptops: " total_laptops "\n"
"Total price of Tablets: " total_tablets);
}
}
I searched here in StackOverflow and read various things about polymorphism and inheritance, but didn't found any specific solution, and the remote things i found doesn't work. I think that the error it's for the way I declared things or some memory management thing in java, I don't know yet, I'm a newbie.
The challenge indicate that need to work with that structure and all that classes, I didn't choose it. My Sin it's the code inside, not the variables or the classes that are defined, even how the class App
it's written, each one of this are indicated in a Class Diagram and the explanation of the challenge, I wanted to do it because I never worked with UML Diagram in OOP and want to give it a try coding one.
Extra
Here is a "test not a real test" i made to see if the problem was with the classes itself or something like that, and discover the classes work individually, when each one it's declared on his own variable, and there isn't other related class in the method.
Here its an external class where I summon each class and try to see another approach to the problem.
public class Test {
public static void main(String[] args) {
float device_cost = test_device(),
tablet_cost = test_tablet(),
laptop_cost = test_laptop();
System.out.println( "Device: " device_cost "\n"
"Tablet: " tablet_cost "\n"
"Laptop: " laptop_cost "\n");
without_father();
all_at_once();
// Outputs are:
// Device: 700.0
// Tablet: 110.0
// Laptop: 580.0
// Tablet without father: 580.0
// Laptop without father: 580.0
// Device in group: 580.0
// Tablet in group: 580.0
// Laptop in group: 580.0
}
static float test_device() {
Device test_device = new Device((byte) 3, 600, 'D');
return test_device.calc_price();
}
static float test_tablet() {
Tablet test_tablet = new Tablet();
return test_tablet.calc_price();
}
static float test_laptop() {
Laptop test_laptop = new Laptop((byte) 3, 500,'E', 250);
return test_laptop.calc_price();
}
static void without_father() {
Tablet test_tablet = new Tablet();
Laptop test_laptop = new Laptop((byte) 3, 500,'E', 250);
System.out.println( "Tablet without father: " test_tablet.calc_price() "\n"
"Laptop without father: " test_laptop.calc_price() "\n");
}
static void all_at_once() {
Device test_device = new Device((byte) 3, 600, 'D');
Tablet test_tablet = new Tablet();
Laptop test_laptop = new Laptop((byte) 3, 500,'E', 250);
System.out.println( "Device in group: " test_device.calc_price() "\n"
"Tablet in group: " test_tablet.calc_price() "\n"
"Laptop in group: " test_laptop.calc_price() "\n");
}
}
CodePudding user response:
Update
I resolved the problem thanks to @ScaryWombat user in the comments of question. So the problem was in how i declared 2 things:
The variables, when declared static, were used by all the classes. So, i declared as protected in the class Device and as private in all the other classes.
The method calc_consume_w has the same problem, because i declared as static, so i change it to public.
This two changes resolved the problem, the class App stay the same.
The new code:
class Device
public class Device { protected float price, basis_price = 100f; protected byte weight, basis_weight = 1; protected char consumption_w, basis_consumption_w = 'F'; // ... public float calc_consume_w() { HashMap<Character,Float> cost_w = new HashMap<Character,Float>(); cost_w.put('A', 100f); cost_w.put('B', 80f); cost_w.put('C', 60f); cost_w.put('D', 50f); cost_w.put('E', 30f); cost_w.put('F', 10f); return cost_w.get(Character.toUpperCase(consumption_w)); } // ... }
class Tablet:
public class Tablet extends Device { private float ram, basis_ram = 1; // ... }
class Laptop:
public class Laptop extends Device { private float hd, basis_hd = 250; // ... }
class TotalPrice:
public class TotalPrice { private float total_devices, total_laptops, total_tablets; private Device[] devices; // ... }