I have a text file that reads in information of various employees.
I've created two array list that are based on the years of an Employee object. The Employee has two subclasses, Salesman and Executive. I'm wondering how I should split it by commas if there's two subclasses, since I can't call the super class
Here's the employee class
public class Employee
{
private String name;
private double monthlySalary;
public Employee(String line)
{
String[]split=line.split(",");
name=split[0];
monthlySalary=Double.parseDouble(split[1]);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getMonthlySalary() {
return monthlySalary;
}
public void setMonthlySalary(double monthlySalary) {
this.monthlySalary = monthlySalary;
}
public double annualSalary()
{
return monthlySalary*12;
}
public String toString()
{
String str;
str="Name: "+name;
str+="\nMonthly Salary: "+monthlySalary;
return str;
}
}
The Salesman class
public class Salesman extends Employee
{
private double annualSales;
public Salesman(String name, double monthlySalary, double annualSales)
{
super(name,monthlySalary);
this.annualSales=annualSales;
}
public double getAnnualSales() {
return annualSales;
}
public void setAnnualSales(double annualSales) {
this.annualSales = annualSales;
}
public double annualSalary()
{
double commision=annualSales*0.02;
if (commision>20000)
{
commision=20000;
}
double totalSalary=super.annualSalary()+commision;
return totalSalary;
}
public String toString()
{
return super.toString()+"\nAnnual Sales: "+annualSales;
}
}
The Executive class
public class Executive extends Employee
{
private double stockPrice;
public Executive(String name, double monthlySalary, double stockPrice)
{
super(name,monthlySalary);
this.stockPrice=stockPrice;
}
public double getStockPrice() {
return stockPrice;
}
public void setStockPrice(double stockPrice) {
this.stockPrice = stockPrice;
}
public double annualSalary()
{
double bonus=0;
if(stockPrice>50)
{
bonus=30000;
}
double totalSalary=super.annualSalary()+bonus;
return totalSalary;
}
public String toString()
{
return super.toString()+"\nStock Price: "+stockPrice;
}
}
And the driver class
import java.io.*;
import java.util.*;
public class employeeDriver
{
public static void main(String[] args)
{
String input;
Scanner readInput=null;
Scanner readFile = null;
try
{
readFile=new Scanner(new File("C:\\mywork\tester.txt"));
}
catch(FileNotFoundException e)
{
System.out.println("The file can't be opened");
System.exit(0);
}
List<Employee> firstList= new ArrayList<>();
List<Employee> secondList= new ArrayList<>();
while(readFile.hasNextLine())
{
//To be inserted
}
}
}
I with split method you mean something that parse the file, I think you should place this login in another class, that have nothing to do with Employee.
This could be something like ParseEmployeeFile or ScanEmpoyeeFile, with a method parse() or scan().
This method should return a standard record, a List or a Map, depends on your needs.
From this record you should be able to create the proper Employee.
To do that, you need what is called a Factory class.
This is a class that contains the logic to create the proper Employee subclass object.
For example:
class EmployeeFactory {
public static Employee create(Record record) {
if (record.get("annualSales") != null) {
return new Salesman(record.get("name"),
record.get("monthlySalary"),
record.get("annualSales"));
}
if (record.get("stockPrice") != null) {
return new Executive(record.get("name"),
record.get("monthlySalary"),
record.get("stockPrice"));
}
return new Employee(record.get("name"),
record.get("monthlySalary"));
}
}
This can be improved as needed.
I guess the input text file contains lines and each of them consists of information of an employee concatenated with commas, like csv file.
In my opinion, you should not use String#split() in the Employee and its subclasses code. After reading file completed in success, then split every line into each attributes (like name and monthlySalary), and then pass them to constructors of Employee or its subclasses.
By clearly distinguishing getting information of the file with making Employee objects, Employee class becomes robuster. For example, please assume information to create Employee objects came from another format (like xml file)? You cannot cope with that easily if you call String#split() inside of Employee's constructor!
Related
I've been wondering is there any way to call a method for EVERY object of one specific class?
Let's say I have a class:
public class Employee {
private double salary;
private boolean hired;
public double getSalary() {return salary;}
public double setSalary(double x) {salary=x;}
public boolean getHired() {return hired;}
public boolean setHired(boolean check) {hired=check;}
}
then I declare another class that extends Employee, e.g. Boss (because Boss is an employee too, right)
so he inherits "gets" and "sets" from Employee and also has the possibility to fire employee:
public class Boss extends Employee {
public void fireTheGuy(Employee unluckyYou) {
boolean temp;
temp=false;
unluckyYou.setHired(temp);
unluckyYou.setSalary(0.0);
}
this allows in main:
public static void main(String args[])
{
Employee worker1 = new Employee();
Employee worker2 = new Employee();
Boss slacker = new Boss();
slacker.fireTheGuy(worker1);
slacker.fireTheGuy(worker2);
}
but what if I have like 100 employees and the Boss wants to fire them all? how this method should be called (is this even possible by some kind of loop?)
You could make all employees register themselves in a common static List. Then when the boss is told to fire everyone he just walks the list.
static List<Employee> allEmployees = new ArrayList<>();
public class Employee {
private double salary;
private boolean hired;
public Employee() {
// All employees must register themselves in the allEmployees list.
allEmployees.add(this);
}
public double getSalary() {return salary;}
public double setSalary(double x) {salary=x;}
public boolean getHired() {return hired;}
public boolean setHired(boolean check) {hired=check;}
}
public class Boss extends Employee {
public void fireTheGuy(Employee unluckyYou) {
unluckyYou.setHired(false);
unluckyYou.setSalary(0.0);
}
public void fireThese(Iterable<Employee> fireThem) {
for ( Employee e : fireThem ) {
fireTheGuy(e);
}
}
public void fireEveryone() {
fireThese(allEmployees);
}
}
This is an example of code of what you could do
List<Employee> employees=new ArrayList<Employee>();
employees.add(worker1);
employees.add(worker2);
for(Employee worker:employees){
slacker.fireTheGuy(worker);
}
But like mentionned in the comments you should try to understand all the concepts behind this example.
public abstract class Employee {
String name;
String position
public Employee(String name, String position) {
this.name = name;
this.position = position
}
}
public class Pilot extends Employee {
public Pilot(String name,String position) {
super();
}
public void flight() {//flight the plane}
//getter and setter for the fields
}
public class Attendance extends Employee {
public Attendance(String name,String position) {
super();
}
public Food servingFood(String foodName) {}
}
// there will be many other positions
public class Company {
HashMap<String, ArrayList<Employee>> employeeTable; //values is a list of workers, key is the position
public Company() {this.employeeTable = new HashMap<>();}
public initializeEmployeeTable(file) {} //read file, and create keys in map (file contains information of the position)
public Worker hireEmployee(String position, String name){
if (position.equals("pilot")) {
Pilot p = Pilot(name);
employeeTable.get("pilot").add(p);
return p
}
else if (position.equals("flightAttendance")) {// the else if statement continuous to check the other position; }
}
public Worker callEmployee(String position, String name) {
for ( Employee e : employeeTable.get(position) ) {
if e.getName().equals(name) {
return e;
}
}
return null;
}
public static void main(String[] args) {
Company company = new Company();
company.initializeEmployeeTable(filePath);
File eventFile = new File(filePath); // event file describes what's happening in real world; read the lines, and call the program so that program simulates the real world events
sc = new Scanner(eventFile);
do {
String currentEvent = sc.nextLine();
String[] currentEventParts = currentEvent.split(", ");
if (currentEvent[0].equals("New Airplane")) { // currentEvent looks like {"New Airplane", "Attendance"// this part can be other position name, "Linda"}
Worker w = company.hireEmployee(currentEventParts[1], currentEventParts[2]); }
else if ((currentEvent[0].equals("flying"))) {
Worker w = company.callEmployee(currentEvent[0], currentEvent[1])
if (w.getPosition().equals("Pilot")) {(Worker) w.flight()}
if (w.getPosition().equals("Attendance")) {(Worker) w.serveFood()}
}
}
The reason there is HashMap for employee because there will be many positions; and reading the event file (when the first index is "New Airplane"); I don't want to go check the following index (would be name and position) with so many if statements to create corresponding employee. But when comes to calling specific methods, I need type casting now; since each method can be different (different type parameter, return type); so it's not ideal to have this methods be abstract method in super class employee and have the subclass implements the body.
Any advices: employee data structure; reading file strategy, pattern design would be appreciated. thanks
The book I am reading says I cant, but my program proves otherwise. For example the code below compiles well, even though i try to access the private properties of the parent class. Then I can freely print them. Can anyone tell me if the book is wrong, or am I doing something wrong?
class Asset
{
private int Id;
private String type;
public int getId()
{
return Id;
}
public String getType()
{
return type;
}
public void setId(int Id)
{
this.Id=Id;
}
public void setType(String type)
{
this.type=type;
}
public void printDescription()
{
System.out.println("Asset Id: "+Id);
System.out.println("Asst type: "+ type);
}
}
class BankAccount extends Asset
{
private String bankName;
private int accountNumber;
private float balance;
public String getBankName()
{
return bankName;
}
public int getAccountNumber()
{
return accountNumber;
}
public float getBalance()
{
return balance;
}
public void setBankName(String bankName)
{
this.bankName=bankName;
}
public void setAccountNumber(int accountNumber)
{
this.accountNumber=accountNumber;
}
public void setBalance(float balance)
{
this.balance=balance;
}
public void printDescriptionnn()
{
System.out.println("The Bank name is: "+ bankName);
System.out.println("Account number: "+ accountNumber);
System.out.println("Your balance is: "+ balance);
}
}
public class AssetTest
{
public static void main(String[] args)
{
BankAccount llogari= new BankAccount();
Scanner input = new Scanner(System.in);
Scanner sinput= new Scanner(System.in);
System.out.print("Type the ID of your asset: ");
llogari.setId(input.nextInt());
System.out.print("Type the type of your asset: ");
llogari.setType(sinput.nextLine());
System.out.print("Give the bank name: ");
llogari.setBankName(sinput.nextLine());
System.out.print("Type the Account Number: ");
llogari.setAccountNumber(input.nextInt());
System.out.print("Type your balance: ");
llogari.setBalance(input.nextFloat());
llogari.printDescription();
llogari.printDescriptionnn();
}
}`
You can access them through public or protected getters but you can't access the private properties directly. In your example, you're using the public setters to modify the property. You can access them through public method !
So to answer you question, private members are not inherited by subclasses. Alternatively, you can have protected members that are inherited by subclasses.
EDIT
From Java Language Specificiation
Members of a class that are declared private are not inherited by subclasses of that class.
Only members of a class that are declared protected or public are inherited by subclasses declared in a package other than the one in which the class is declared.
Because you're not directly modifying the parent class's elements. You're calling public functions that modify the private elements, which is completely valid.
A subclass does not have direct access to the private members of a super class. It only has direct access to the public and protected members.
In this context, direct access means: super.member
If the super class implements protected or public accessor or mutator methods, then you may be able to indirectly access them. Indirect access would look something like: super.getMember() or super.doSomething().
Any subclass does not have permission to direct access of the private members of a super class. It can access to the public and protected members.
I want to be able to give a specific value to discount depending on certain requirements like the following age: > 25 and profession = teacher / professor get 10% discount, age < 25 and gradepoint > 7 get 25% discount
this is my code so far I am using double OO paradigm:
public class customer {
//attribute definitions
private String name;
private String address;
private String profession;
private Integer age;
private Integer gradepoint;
private double discount;
//constructor
public customer(String newName, String newAddress, String newProfession, Integer newAge, Integer newGradepoint, double newDiscount)
{
setName(newName);
setAddress(newAddress);
setProfession(newProfession);
setAge(newAge);
setGradepoint(newGradepoint);
setDiscount (newDiscount);
}
//getters
public String getName()
{ return name;}
public String getAddress()
{ return address;}
public String getProfession()
{ return profession;}
public Integer getAge()
{ return age;}
public Integer getGradepoint()
{ return gradepoint;}
public double getDiscount()
{ return discount;}
//setters
public void setName (String newName)
{ name = newName;}
public void setAddress (String newAddress)
{ address = newAddress;}
public void setProfession (String newProfession)
{ profession = newProfession;}
public void setAge (Integer newAge)
{ age = newAge;}
public void setGradepoint (Integer newGradepoint)
{ gradepoint = newGradepoint;}
public void setDiscount (double newDiscount)
{ discount = newDiscount;}
//methods
}
Would I need to create a sub class called discount or each type of discount? or I can write a method directly into this customer class to control the discount?
write a method directly into this customer class to control the discount?
This. Make it a calculated field. Kill setDiscount function, kill discount variable, and make the getDiscount function into something like:
public double getDiscount() {
if (...) return ...;
if (....) return ...;
...
}
...unless you want to have this as the default discount, and still allow modification, in which case keep discount as a property, and move this whole logic into the constructor, having conditional setDiscount() calls.
Your getDiscount function would ideally do the calculation and return the appropriate discount for the current object. For example:
public double getDiscount()
{
if (getAge() < 25 && getGradepoint() > 7)
{
return .25;
}
else if // other logic...
}
Although not the simplest solution, I would abstract the discount calculation to a separate interface and class as well as having an override discount value in the customer object.
E.g.
public interface DiscountManager<T>
{
public double getDiscount(T discountObject);
}
public abstract class AbstractCustomerDiscountManager extends DiscountManager<Customer>
{
public double getDiscount(Customer customer)
{
if (customer.hasCustomDiscount()) { return customer.getDiscount(); }
else { return calculateDiscount(customer); }
}
public abstract double calculateDiscount(Customer customer);
}
public class DefaultDiscountManager extends AbstractCustomerDiscountManager
{
public double calculateDiscount(Customer customer)
{
double discount = 0;
if ((customer.getAge() != null) && (customer.getAge() < 25)) { discount += 25; }
...
return discount;
}
}
Probably over time different rules evolve. At the spot where the discounting takes place, in the order, the discount and and a reference to the rule applied should be stored together.
This kind of business logic could have its own class. A generic solution would even be to store the rule as scriptable code (BeanShell = Java, or JavaScript) and use java's scripting API. So that this kind of business logic resides more with the business managers, and the rules can be presented and edited.
Currently I have two classes. A Classroom class and a School class. I would like to write a method in the School class public void showClassRoomDetails which would find the classroom details by only using the teacherName.
e.g.
teacherName = Daniel className = Science
teacherName = Bob className = Maths
so when I input Bob, it would print out Bob and Maths
many, thanks
public class Classroom
{
private String classRoomName;
private String teacherName;
public void setClassRoomName(String newClassRoomName)
{
classRoomName = newClassRoomName;
}
public String returnClassRoomName()
{
return classRoomName;
}
public void setTeacherName(String newTeacherName)
{
teacherName = newTeacherName;
}
public String returnTeacherName()
{
return teacherName;
}
}
import java.util.ArrayList;
public class School
{
private ArrayList<Classroom> classrooms;
private String classRoomName;
private String teacherName;
public School()
{
classrooms = new ArrayList<Classroom>();
}
public void addClassRoom(Classroom newClassRoom, String theClassRoomName)
{
classrooms.add(newClassRoom);
classRoomName = theClassRoomName;
}
public void addTeacherToClassRoom(int classroomId, String TeacherName)
{
if (classroomId < classrooms.size() ) {
classrooms.get(classroomId).setTeacherName(TeacherName);
}
}
public void showClassRoomDetails
{
//loop
System.out.println(returnClassRoomName);
System.out.println(returnTeacherName);
}
}
Do you really need a list here ?
A Map holding classroom - teacher associations would be more helpful for what you're trying to achieve.
But there are also strange things in your code: for instance, why do you hold a classRoomName and teacherName as instance variables in your School class ?
Change your method signature to take a targetTeacherName as a parameter. Loop through the classrooms until you find one with that teacher. Output the information of that classroom.
Since you are using an ArrayList you could simply use a for each statement:
public void showClassRoomDetails(String teacherName)
{
for (Classroom classroom : this.classrooms)
{
if (classroom.returnTeacherName().equals(teacherName))
{
System.out.println(classroom.returnClassRoomName());
System.out.println(classroom.returnTeacherName());
break;
}
}
}
As a small suggestion, do not name your methods returnXxx(), use getXxx() instead, it is the standard Javabean convention.