Overriding and Inheritance - java

i am having problems with my codes. this is our assignment:
"Write a superclass named clsWorker and subclasses clsHourlyWorker and clsSalariedWorker. Every worker has a name and a salary rate. Write a method computePay(int hours) that computes the weekly pay for every worker. An hourly worker gets paid the hourly wage for the actual number of hours worked if hours is at most 40. If the hourly worker worked for more than 40 hours, the excess is paid at time and a half. The salaried worker gets paid the hourly wage for 40 hours, no matter what the actual number of hours is. Write a test program for the inheritance. Input the name of the worker, the number of hours worked and the type of worker, H for hourly and S for salaried, the salary rate of the worker. Display the salary of every worker entered."
we need to do overriding and inheritance. i always encounter the NoSuchMethodError
My superclass:
public class clsWorker
{
int hours=0,excess=0;
double salary,newSalary=0.0;
String sType;
public clsWorker()
{
}
public clsWorker(double sal,String type)
{
//this.hours=hours;
salary=sal;
sType=type;
}
public double computePay(int hours)
{
sType=sType.toUpperCase();
if(sType.equals("H"))
newSalary=(salary*hours)*7;
else if(sType.equals("S"))
{ if(hours>=40)
newSalary=salary*40;
else if(hours>40)
{
excess=hours-40;
newSalary=(newSalary+((newSalary*excess)*1.5))*7;
}
}
return newSalary;
}
}
My subclasses
public class clsHourlyWorker extends clsWorker
{
double dSalary=0.0;
int iHours=0;
public clsHourlyWorker()
{
//super();
}
public clsHourlyWorker(int iHours, double salaryph,String sRate)
{
super(iHours,salaryph,sRate);
//clsWorker w=new clsWorker();
dSalary=newSalary;
}
public double getSalary()
{
return dSalary;
}
}
public class clsSalariedWorker extends clsWorker
{
double dSalary=0.0;
int iHours=0;
public clsSalariedWorker()
{
//super();
}
public clsSalariedWorker(int iHours,double salaryph,String sRate)
{
super(iHours,salaryph,sRate);
//super(salaryph,sRate);
//this.iHours=iHours;
//clsWorker w=new clsWorker();
dSalary=newSalary;
}
/*public void setSalary(int iHourjs)
{
}*/
public double getSalary()
{
return dSalary;
}
}
my test class
import java.util.*;
public class testSalary
{
public static void main(String[]args)
{
Scanner console=new Scanner(System.in);
System.out.println("Input Salary per hour: ");
double salaryph=console.nextDouble();
System.out.println("Input number of hours: ");
int iHours=console.nextInt();
console.nextLine();
System.out.println("Input Worker Name: ");
String sName=console.nextLine();
System.out.println("Input Type of Worker: ");
String sRate=console.next();
clsHourlyWorker hw=new clsHourlyWorker(iHours,salaryph,sRate);
clsSalariedWorker sw=new clsSalariedWorker(iHours,salaryph,sRate);
//System.out.println("Worker Name: "+sName+"\nSalary: "+hw.getSalary());
if(sRate.equals("H"))
System.out.println("Worker Name: "+sName+"\nSalary: "+hw.getSalary());
else if (sRate.equals("S"))
System.out.println("Worker Name: "+sName+"\nSalary: "+sw.getSalary());
}
}
can someone tell me how to fix my problem? thanks.

This doesn't make sense:
public clsHourlyWorker(int iHours, double salaryph,String sRate)
{
super(iHours,salaryph,sRate);
//clsWorker w=new clsWorker();
dSalary=newSalary;
}
Since the super class's constructor doesn't take int, double, and String but rather, it takes String, double, int representing name, dRate, and hours. Also is sRate really supposed to be a String? I strongly doubt it.
I suggest that your child class constructor accept in the parameter all the information needed for the super constructor (a Strinng for name, double for dRate and int for hours) plus additional parameters the additional information for the new child class fields. You may wish to re-think those fields though as some seem to be duplicates of the super's fields and thus unnecessary.

A couple of things could be improved:
Use inheritance
Simply put, the code you posted does not leverage the power of inheritance at all. You created two subclasses, but all they do is delegate the payment computation back to the superclass. Make clsWorker abstract, make computePay abstract and implement two different versions of the method in the subclasses:
public abstract class Worker {
// ...
public abstract double computePay(int hours);
}
public class HourlyWorker extends Worker {
// ...
#Override
public double computePay(int hours) {
// code from the 'sType.equals("H")' block
}
}
public class SalariedWorker extends Worker {
// ...
#Override
public double computePay(int hours) {
// code from the 'sType.equals("S")' block
}
}
Now you will also realize that the field sType is not serving any useful purpose. In fact, this approach would be required only if polymorphism was not supported by Java. You already know (when writing the code) whether you're dealing with an HourlyWorker or a SalariedWorker because you put the code either in HourlyWorker's computePay or in SalariedWorker's computePay.
sType does not provide any new information that we would not already know from looking at the inheritance hierarchy. This way, you're giving the exact same information twice (once by inheritance, once by sType), which is something we're generally trying to avoid in software development.
Improve "test" class
(I put "test" in quotes because most developers would think that by "test" class, you mean some sort of automated, unit-testing "test" - e.g. a JUnit test case.)
First thing that seems odd is: Why instantiate both a HourlyWorker and a SalariedWorker (i.e. new clsHourlyWorker, new clsSalariedWorker), if the user can choose to either create a HourlyWorker or a SalariedWorker before (but not both, this is 'exclusive or')?
What you really want is something along the lines of:
Worker w;
if(sRate.equals("H"))
w = new HourlyWorker(iHours,salaryph);
else if (sRate.equals("S"))
w = new SalariedWorker(iHours,salaryph);
else
throw new Exception("Don't recognize worker type: " + sRate);
System.out.println("Worker Name: "+sName+"\nSalary: "+w.getSalary());
As you can see, it is valid to use the abstract superclass Worker as the type for your worker instance variable, w, if you don't know at this point (during runtime) whether the user will choose H or S. You only need to access getSalary, which is declared in Worker, so everyhing is fine. (If you ever later needed to access a method which is implemented only by a subclass, you could still type-cast it.)
You will also realize that you need only one println. Again, we'd like to minimize duplication in favor of abstraction. Both lines do basically the same, they print name and computed salary of a worker, so we try to reduce two lines to one, more abstract line of code.
Second, you might also, instead of printing sName directly, want to have a getter (getName) in Worker. When you get to work on larger projects, you'll see that input and output can happen at a very different time and place (e.g. Worker might be stored in a database and the original variable sName will be long gone when a different user retrieves the Worker from the database). So be prepared to get all required data from your real objects, not the test input.
Third - but I might be mistaken here - "Display the salary of every worker entered" sounds to me like you're supposed to implement a while loop where the user can enter multiple workers. But then, there are more important things you can learn from this assignment.
Follow naming conventions
In Java, it is very common practice to have uppercase class names and lowercase method names. Normally you'd have Worker, HourlyWorker and SalariedWorker (see code sample above). This way, every Java developer in the world can already tell we're talking about classes.
However, for your assignment, I'd suggest you follow whatever arbitrary "conventions" there are - just keep in mind that this is not the standard Java way. Read up on naming conventions (general and particular) before you do something like this in real-world projects.

Related

Better way to write many if statements in Java?

So I have this homework where I need to build a vending machine, and I assigned a coordinate to every product (A1, A2, A3..) and when the user enters the coin value I have to calculate if he can buy the product that he chose and if yes calculate the change, since i'm still new to programming I now have ended up with many statements like this
if ("a1".equals(choice)) {
System.out.println("You chose SNICKERS!");
if (money < 50) {
System.out.println("This is not enough money to buy this product");
} else if (money >= 50) {
System.out.println(" Price = 50 Your change = " + (money - 50));
}
}
where the only things changing are the coordinates (a1, a2, a3, a4, b1, b2 and so on) and the prices. What would be a better way to do this?
You could use a more OO approach.
Make a class called Product:
class Product {
private String name;
private int price;
public String getName() { return name; }
public int getPrice() { return price; }
public Product(String name, int price) {
this.name = name;
this.price = price;
}
}
Then, create a HashMap<String, Product> and add all your products and their coordinates in:
HashMap<String, Product> productMap = new HashMap<>();
productMap.put("A1", new Product("Snickers", 50));
productMap.put("A2", new Product("Something else", 40));
// do this for every coordinate...
Now, you can just use this code:
Product chosenProduct = productMap.get(choice);
System.out.println("You chose " + chosenProduct.getName() + "!");
if (money < chosenProduct.getPrice()) {
System.out.println("This is not enough money to buy this product");
} else {
System.out.println(" Price = " + chosenProduct.getPrice() + " Your change = " + (money - chosenProduct.getPrice()));
}
This is a common moment in programming and you're right to think there's a better way to go about it.
In your particular case, where you have a similar structure of code in many places, you should try using a function. Try writing a private function in the same class that takes in some of the parameters that change. Depending on the level of complexity you end up with you might end up with a large function with a lot of parameters which isn't great either. Regardless, writing a function is probably the first place you should go when you encounter this situation.
Secondarily, consider what this segment of code is doing. Making a generic function to replace the whole code segment might not be ideal but could you easily write a function to do a small part of it? If so, is it now easy to make the rest into another function? Keep track of any variances you have across your many similar code segments, if any, and try to create functions that address those variations.
Finally, depending on what is in scope for your current level of programming, you might be able to create data structure to help with the identification of the choice. For example, maybe you could make a map where you could store each of the choices and an associated object that contains all of the data you need to respond to the user (i.e. cost, item name, etc.). With that kind of approach you can pre-populate all of those options in a straightforward manner and have your code simply look up the set of data associated with the choice and call of function to print the necessary output.
Ultimately, how you go about this and future situations like it is highly dependent upon what your level of experience with programming, how many choices there are, and how complex the data associated with each choice is.
Continue to trust your instincts though, they will serve you well.
Switch case is the desired functionality.
switch(choice) {
case 'a' : <some code>
break;
case 'b': <some other code>
break;
default: <if none of the choices matched>
}
The only caveat is that your choice value has to be a char or an int
EDIT:
This was a bad answer from my side. Clearly, you need a more cleaner way to write your vending machine.
A good way to structure it would be to first create a Product class which can store the name and the price of the product.
class Product {
private String name;
private String price;
// Implement a constructor and an equals() method to equate two
// instances of product
}
You could then create a function (which could be used in your main()) which takes the text input from your user and map it to an actual product.
public static Main(String[] args) {
// ...
private Product processUserInput(String productName) {
// Add logic to process the string and return a Product
}
// ...
}
Then you could add a function that would process the Product and the amount the user has and return the change remaining or maybe -1 if the product costs more than the available amount.
public static Main(String[] args) {
// ...
private int processUserProductChoice(Product product, int amountAvailable) {
// Add logic to process the product and amount
// Probably use switch case now.
}
// ...
}

Java - Method declared but cannot reference it

I am kind of new to Java, although I've programmed in other procedural langauages for 25 years. So, I'm trying to teach myself Java. Trying to write some silly program consisting of two files: a Class called "Customer", and a main program called "Silly4".
I'm pretending to implement a credit card system for a bank type company (even though the majority of my experience was in defense contracting). I figure this would be a good teaching example for me.
Trying to build a credit card data structure called "Customer" such that (for the time being) it can accomodate 1000 customers. In the main program "Silly4", I instantiate this Customer class as "cust2", and then from there I attempt to work with "cust2". I try to retrieve customer number 5's (j=5) credit card balance. So far, so good.
Then from there I attempt to declare in the class Customer another method (for future use) which I arbitrarily call "bal44", and then I attempt to reference it in the main program Silly4 as " ball44(5541);".
So I compile class Customer, then compile program Silly4, and I'm getting a compile error "java:52: error: cannot find symbol" for the reference to method "bal44(5541)" in main program "Silly4". I'm confused. I've declared and successfully compiled the class Customer with "bal44" in there, but Java is telling me it can't find it. I'm confused.
Please excuse all the extraneous println's, I use them to see how the program is moving along.
Here is class Customer:
// Data Structure for credit card database
public class Customer {
private String name;
private int accountNo;
private double balance;
private boolean Overdue;
// Getters, setters, constructor...
public void setName( String new_name )
{ name = new_name; }
public void setAccount( int new_account )
{ accountNo = new_account; }
public void setBalance( double new_bal )
{ System.out.println( " Start proc setBalance ");
balance = new_bal;
System.out.println( " Finish proc setBalance ");
}
public double getBalance()
{ System.out.println( " Start proc getBalance ");
System.out.println( " proc getBalance , balance= " + balance + " end print");
return balance;
// how to specify which element of array[1000] ? balance I want ?
// System.out.println( " Finish proc getBalance ");
}
// Add new customer to credit card system
// (note - index in array Customer[i] is worry of main program
//
public void addCustomer( String name2, int account2, double bal2 )
{ name = name2;
accountNo = account2;
balance = bal2;
}
public void bal44 ( int account3 )
{ accountNo = account3; }
// Constructor
Customer ()
{ name = "John Smith";
accountNo = 1005;
balance = 125.43;
Overdue = false; }
// see page 1032 Liang for definition complex Object and get-Procs for it
}
Here is main program/class Silly4:
class Silly4
{
// Program for credit card database
public static void main(String[] args)
{
double bal2, bal3;
int i; // loop counter
int j;
bal2 = 151.47;
bal3 = 5.0; // just initialize
// And then you can create an array of it:
System.out.println("** Program Silly4 Running **");
Customer[] cust2 = new Customer[1000];
System.out.println("** Array cust2 instantiated **");
for(i=0; i<=999; ++i)
{
cust2[i] = new Customer();
}
System.out.println("** Array2 cust2 Obj initialized **");
// try to code this eventually - cust2.balance = 151.47 ;
//
j = 5; // customer no. 5
cust2[j].setBalance( bal2 );
bal3 = cust2[j].getBalance() ;
System.out.println("** Balance Customer " + j + " is " + bal3);
// Add a new customer
// comment out - addCustomer( "Steve Jones", 5541, 1.0 );
bal44( 5541 ); // test out declaring new method "bal44"
System.out.println("** End of Silly4 **");
}
}
You basically answered yourself in the first sentence of your query. Java is not a purely procedural language, it's an object-oriented language.
That means that when you declare methods, they are not just scoped functions. A method declared in a class is not similar to a function declared in an included file in C. It's something that can be only called from the scope of an object of the enclosing class. In other words, you don't have a function named bal44. You have a method bal44 of class Customer, which means that you need to ask an object fo class Customer to execute it for you, similar to how you call setBalance().
EDIT: As another comment mentions, what might be confusing you more is that whenever you use a method name without qualifiers, Java treats it as a shortcut of asking this (the current object) to execute the method, so technically, method(args) is a shortcut for this.method(args). Therefore, whenever you are within the scope of a single class, a class's methods will behave almost as traditional functions.
When you call
bal44( 5541 );
Without any object, Java assumes it as a "this" object and searches for that method in Silly4 not in Customer class. Call that method from Silly4 like you are calling other method of customer class.
e.g.
cust2[j]. bal44( 5541 ); or something like that.
Read more about "this" here https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html
P.S. A bonus point to note here is that static method's like main method do not have this reference available to them. So, technically here it is searching for a class-level(static) method in Silly4 rather than instance method. :)
See, here is the problem : You are using the bal44(5541), but you made that method non static, meaning you need to make an object of your class (Customer) and then say for example
Customer customer = new Customer()
customer.bal(5541);
If you want to call that method without making an object of its class, simply put the keyword "static" in the method's header. public static void bal44(int num)
Further explanation : Since you are from a procedural language, recall the main difference is the usage of objects. An object is something that has several traits, or attributes, and actions or behaviors. For example a car, its attributes are its color, speed, etc. and its main action/behavior is drive. Attributes are variables, and Behaviors/Actions are methods. e.g.
car.drive();
car.setColor("red");
I hope that helped? If you don't understand you can PM me or respond here and I'll explain in further detail

saving only doubledigit numbers into my attribute

I got a task for a Season Object which can only save doubledigit integer numbers as the season number.
How can I initialize the value properly so it will only store doubledigit numbers?
I'm not allowed to use methods or my constructor for that.
the only possible solution I found (even though it would be dumb) is to use an enum from 1 to 99.
Is this really the solution? I'm also not allowed to use API classes for that.
Edit:
public class Season {
String name;
Series series;
int seasonNumber;
public Season () { }
}
I didn't post the code on purpose cause it isn't anything that will help
Edit2: (Tl;Dr of the Task)
The Task is to create a Series, Season and Episode Object. Series and Episode aren't of interest as for this question. The Season Object is defined as you can see in the code above.
The overall conditions are as following:
- primitive datatypes, String, enum are allowed and every class I wrote myself.
- no API classes are allowed.
- methods aren't needed.
- constructor isn't allowed to modify my number with regEx or anything like that
This is the best solution I can come up with:
public Season(int seasonNumber) {
if (seasonNumber < 1 || seasonNumber > 99) {
throw new IllegalArgumentException("Value between 1 and 99 (both inclusive) required. Found + " seasonNumber);
}
this.seasonNumber = seasonNumber;
}
I am not using a method, because the logic is all in the constructor. Though I suspect the person who gave you this hasn't got his point across with the assignment texts.
If you want the season number returned as 01, 02, etc., you could create a method that returns a String, instead of an int:
public String getSeasonNumber() {
if (seasonNumber < 10) {
return "0" + seasonNumber;
} else {
return seasonNumber;
}
}

Java RMI- unexpected behavior of threads

I'm new to java rmi and I have issues with synchronization.
The server handles a small data base throw files (7 files,each one represents an university),
the client when connected gives the name of the university then chooses an option :
add a student
remove a student
update a student
search for a student
Everything works fine, but I have a problem with synchronization.It doesn't work the way I expected.
Say we have 3 files, I created 3 private static Integers to use like this
public class CarnetImpl extends UnicastRemoteObject implements Carnet {
private String fac;
private static Integer univ1=1;
private static Integer univ2=1;
private static Integer univ3=1;
CarnetImpl(String fac) throws RemoteException {
this.fac=fac;
}
public void add(Student e) throws RemoteException {
Integer lock=1
switch (fac){
case "univ1":
lock=univ1;
break;
case "univ2":
lock=univ2;
break;
case "univ3":
lock=univ3;
break;
}
synchronized(lock){
//creating a file named "fac.txt" (fac can be univ1,2 or3) and adding a student
}
}
}
I did the same thing for the other methods.
What I expected is that for a given university only one client can use a method,while more than one client can use the same method for different universities at the same time.
But after testing it seems that even for different universities a client have to wait for an other to finish to use the method.
Example :
Client 1 asks the server to add student1 to univ1 (i added a 5' sleep and a println to detect threads behavior ).
Before the end of the 5 seconds client 2 asks the server to add(or any other method) student2 to univ2.
As client2 asked an add on univ2,I expected that lock will take univ2 so the thread wouldn't wait because univ2 is not locked unlike univ1.
Can anyone help me understand ?
Any suggestions to get the expected behavior would be most welcome.
Thanks.
private static Integer univ1=1;
private static Integer univ2=1;
private static Integer univ3=1;
These are three references to the one and the same object, the Integer instance from that class's internal cache of all values between -128 and 128.
You would have avoided this if you kept to the recommended practice to use plain Objects for locks.
I should also comment that your whole design is needlessly roundabout: since fac is fixed at instantiation time, you would be better off assigning the proper lock object to an instance variable at that point instead of going through the decision cascade on each method call.

Sorting Arraylists of custom objects without using interfaces

Sorry, this might be duplicated, I'm not sure if my previous attempt to post this went through.
Started to learn Java several weeks ago, working on one of my first assignments. :)
My question is somewhat basic, but I couldn't find its exact equivalent after looking through previously resolved topics. This isn't a real life problem, so I guess it's expected from me to tackle it in a very specific way.
So the task consisted of several steps - I had to create a superclass with a number of custom objects, add new subclasses, implement new methods to count the value of certain variables, write test classes and sort my output.
It's all been done apart from this last step. Not sure if I'm allowed to just post my problems like that on the web, but here is where I am right now:
I have something like:
public class Pants
{
public enum SizeType {SMALL, MEDIUM, LARGE, EXTRA_LARGE}
private SizeType size;
private String brand;
private String countryOfOrigin;
private String color;
private double price;
//Other variables and methods
}
public class Jeans extends Pants
{
//new variables and methods
}
public class Shorts extends Pants
{
//some more new variables and methods
}
And other similar subclasses.
import java.util.ArrayList;
public class Selection
{
public static void main(String[] args){
Jeans ex1 = new Jeans("John Lewis");
ex1.countryOfOrigin("US");
ex1.color("Navy");
ex1.setSize(Pants.SizeType.LARGE);
ex1.setprice(40);
ex1.machineWashable(true);
System.out.println(ex1);
Shorts ex2 = new Shorts("Ted Baker");
ex2.countryOfOrigin("United Kingdom");
ex2.color("White");
ex2.setSize(Pants.SizeType.MEDIUM);
ex2.setprice(30);
ex2.machineWashable(true);
System.out.println(ex2);
//..etc
ArrayList<Pants> selection = new ArrayList<Pants>();
selection.add(ex1);
selection.add(ex2);
selection.add(ex3);
selection.add(ex4);
selection.add(ex5);
System.out.println( "Size - LARGE: " );
System.out.println();
Pants.SizeType size;
size = Pants.SizeType.LARGE;
ListPants(selection,size);
I need to write a ListPants method to list objects depending on SizeType - starting with large in this case. I don't think I can implement any additional interfaces (which is what was mostly recommended in other threads).
Please see my attempt below (didn't work). Am I thinking in the right direction here, or?
public static void ListPants(ArrayList<Pants> selection, Pants.SizeType size)
{
for (Pants.SizeType sizeType : Pants.SizeType.values()) {
for (Pants pants : selection) {
if (pants.getSize().equals(sizeType)) {
System.out.println(selection.toString());
I think it's just a minor problem you're facing. You already defined the signature of the method which should print out all pants of a specific size:
ListPants(ArrayList<Pants> selection, Pants.SizeType size)
That is correct. Now, your code is looping over all pants and over all possible sizes:
public static void ListPants(ArrayList<Pants> selection, Pants.SizeType size)
{
for (Pants.SizeType sizeType : Pants.SizeType.values()) {
for (Pants pants : selection) {
if (pants.getSize().equals(sizeType)) {
System.out.println(selection.toString());
Since this looks like a homework assignment, i'll phrase my answer as a question:
Where are you using the size parameter in the method body of ListPants?
I am assuming your class cannot implement new interfaces, and not using interfaces at all.
You can use Collections.sort(List,Comparator) with a Comparator, which is built for your class.
Something like
Collections.sort(selection,new Comparator<Pants>() {
#Override
public int compare(Pants p1, Pants p2) {
//implement your compare method in here
...
}
});
If you are eager to create your own sorting algorithm, have a look of this list of sorting algorithms. Simplest to implement (though pretty slow) IMO is selection-sort

Categories