I have a problem with a task I have to do. I need to create class Company and write few methods (such as hire, fire, etc.) for Employee class objects.
Those are my classes and methods:
public class Company{
ArrayList <Employee> alist= new ArrayList<Employee>();
public void hire(Employee e) {
int i=0;
boolean k=false;
while(i<alist.size()) {
if (e.getLastName().equals(alist.get(i).getLastName())) {
k=true;
i++;
}
}
if (k==false) alist.add(e);
else System.out.print("Employee already exists");
}
}
public class Employee{
protected String lastname; //protected for subclasses
protected double jobposition;
public Employee(String lastname,double jobposition) {
this.lastname=lastname;
this.jobposition=jobposition;
}
public String getLastName() {
return lastname;
}
And subclass which extends Employee:
public class OfficeWorker extends Employee {
float pay, bonus;
public OfficeWorker(String lastname,double jobposition,float pay,float bonus) {
super(lastname,jobposition);
this.pay=pay;
this.bonus=bonus;
}
}
I wanted to use ArrayList to do this, but it crashes in main class and I get message "The method hire(Employee) is undefined for the type ArrayList":
public static void main(String[]args) {
ArrayList <Employee> list = new ArrayList <Employee>();
Employee e1 = new OfficeWorker("Smith",0.5,2000,50);
list.hire(e1);
}
Why can't I do this like that?
Your main method should be like:
public static void main(String[]args) {
Company company = new Company();
Employee e1 = new OfficeWorker("Smith",0.5,2000,50);
company.hire(e1);
}
As you have already written method hire() in class Company which adds the Employee in the ArrayList <Employee> alist.
There is NO way you can create your own method in Java ArrayList class.
ArrayList list = new ArrayList ();
ArrayList don't have hire method.
In a class you can access the method availabe in that method.And that also depends upon access modifier and where you are aceesing the method.
To access a non-static public method you have to create object and call method on that object
SomeClass c=new SomeClass();
c.m();
For static public method you can call directly
SomeClass.m();
hire() method is defined as part of Company Class.
it should be as below.
Company xyz = new Company();
xyz.hire(e1);
What's happening is that you are calling the method hire directly into the ArrayList object, instead of that, create an object called Company, then, once it's created, call the method of hire in the Company, as the Company already has the property of ArrayList in it.
public static void main(String[]args) {
Company company = new Company();
Employee e1 = new OfficeWorker("Smith",0.5,2000,50);
company.hire(e1);
}
Hope it helps!
Related
I'm very new to java and would like to know whether calling a subclass method in a superclass is possible. And if doing inheritance, where is the proper place to set public static void main.
Superclass
public class User {
private String name;
private int age;
public User() {
//Constructor
}
//Overloaded constructor
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public static void main(String []args) {
User user1 = new Admin("Bill", 18, 2);
System.out.println("Hello "+user1.getName());
user1.getLevel();
}
}
Subclass
public class Admin extends User {
private int permissionLevel;
public Admin() {
//Constructor
}
//Overloading constructor
public Admin(String name, int age, int permissionLevel) {
super(name, age);
this.permissionLevel = permissionLevel;
}
public void getLevel() {
System.out.println("Hello "+permissionLevel);
}
}
Short answer: No.
Medium answer: Yes, but you have to declare the method in the superclass. Then override it in the subclass. The method body from the subclass will be in invoked when the superclass calls it. In your example, you could just put an empty getLevel method on User.
You could also consider declaring User as an abstract class and declaring the getLevel method as abstract on the User class. That means you don't put any method body in getLevel of the User class but every subclass would have to include one. Meanwhile, User can reference getLevel and use the implementation of its subclass. I think that's the behavior you're going for here.
I'm very new to java and would like to know whether calling a subclass
method in a superclass is possible.
A superclass doesn't know anything about their subclasses, therefore, you cannot call a subclass instance method in a super class.
where is the proper place to set public static void main.
I wouldn't recommend putting the main method in the Admin class nor the User class for many factors. Rather create a separate class to encapsulate the main method.
Example:
public class Main{
public static void main(String []args) {
User user1 = new Admin("Bill", 18, 2);
System.out.println("Hello "+user1.getName());
user1.getLevel();
}
}
No, it is not possible to call sub class method inside super class.
Though it is possible to call different implementations of the same method in a client code while you have a variable with a super class type and instantiate it with either super class or sub class objects. It is called polymorphism.
Please, consider the following example:
public class User {
private String name;
private int age;
protected int permissionLevel;
public User() {
//Constructor
}
//Overloaded constructor
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public void getLevel() {
System.out.println("Hello "+ permissionLevel);
}
}
public class Admin extends User {
public Admin() {
//Constructor
}
//Overloading constructor
public Admin(String name, int age, int permissionLevel) {
super(name, age);
this.permissionLevel = permissionLevel;
}
#Override
public void getLevel() {
System.out.println("Hello "+permissionLevel);
}
public static void main(String []args) {
User user1 = new Admin("Bill", 18, 2);
System.out.println("Hello "+user1.getName());
user1.getLevel(); //call to subclass method
user1 = new User("John", 22); //the variable is the same but we assign different object to it
user1.getLevel(); //call to superclass method
}
}
Answering your second question, no, it does not matter where you place your main method as long as it is of right method signature. As you can see in my example I moved the method to Admin.java - it is still acceptable.
Calling subclass method in a superclass is possible but calling a subclass method on a superclass variable/instance is not possible.
In java all static variable and methods are considered to be outside the class i.e they do have access to any instance variable or methods. In your example above it will be wise to create a new class called Main and put public static void main in there but this is just a hygiene issue and what you have above will work except for the line.
user1.getLevel()
Use case: If employee eats, then automatically should sleep:-)
Declare two methods eat and sleep from class person.
Invoke the sleep method from eat.
Extend person in the employee class and override only the sleep method:
Person emp=new Employee();
emp.eat();
Explanation: As eat method is not in subclass, it will invoke the super class eat. From there, sub class's sleep will be invoked.
I'm trying to cover OOP stuffs but I stuck here. I get error in Company class, employees[0].setBonus(50) part. Isn't there any other way to solve it except defining Bonus methods in Employee class? Or is there anyway to keep all objects in one array? I defined bonus methods but there was another thing, what I have to return in Empoyee class' getBonus method?
public class Company
{
private static Employee[] employees;
public Company()
{
employees= new Employee[]{new Manager("Sapo",10000),new Employee("James",5000),new Employee("Jessie",5001)};
}
public static void main(String[] args)
{
Company company= new Company();
employees[0].setBonus(50);
System.out.println(employees[0].getBonus());
}
}
public class Employee extends Person
{
int salary;
public Employee(String name,int salary) {
super(name);
setSalary(salary);
// TODO Auto-generated constructor stub
}
public void setSalary(int salary)
{
this.salary= salary;
}
public int getSalary()
{
return salary;
}
}
public class Manager extends Employee
{
private int bonus;
public Manager(String name, int salary) {
super(name, maas);
}
public void setBonus(int bns)
{
bonus=bns;
}
public int getBonus()
{
return bonus;
}
public int getSalary()
{
return salary+bonus;
}
}
I'm confused.
If you really want do it this way, you can cast employee[0] as manager, but You must know is not nice solution. E.g:
Company company= new Company();
Manager manager = Manager.class.cast(employees[0]);
manager.setBonus(50);
System.out.println(manager.getBonus());
Or is there anyway to keep all objects in one array?
You could but it would force you to write :
if ( employees[0] instanceof Manager){
((Manager) employees[0]).setBonus(50);
}
which is not a good practice.
Functionally, if a bonus is a property which owns only the Manager instances, an Employee instance should not try to set or get it.
When you do :
employees[0].setBonus(50);
the compiler doesn't know the concrete instance. It sees only Employee.
In this very simple code, we see straight that the first employee is a manager but in a real application the array may be modified multiple times. Trying to remember at which indexes are the managers is error prone. If you need to call a manager specific method on a or several managers you should be sure about knowing which variables are managers. So declaring them as manager seems the more natural way.
To solve your problem, two arrays seems more interesting : one for employees and another for managers :
private static Employee[] employees;
private static Manager[] managers;
Now you can do :
public Company()
{
employees= new Employee[]{new Employee("James",5000),new Employee("Jessie",5001)};
managers= new Employee[]{new Manager("Sapo",10000)};
}
public static void main(String[] args){
Company company= new Company();
managers[0].setBonus(50);
System.out.println(managers[0].getBonus());
}
Your abstraction is wrong. You see, the compiler only has that information that is available at compile time.
You have an array of Employee objects there. It doesn't matter that your code at run time will put a Manager object into that array! The compiler doesn't know that. He only knows that there is an Employee.
And the Employee class has no method setBonus(). Thus you can't call that method!
One possible solution would be for example to make the bonus a parameter to the constructor of Manager; the whole think could look like this:
public class Manager extends Employee {
private final int bonus;
public Manager(String name, int salary, int bonus) {
super(name, salary);
this.bonus = bonus;
}
#Override
int getSalary() {
return super.getSalary() + bonus;
}
Notes:
You should avoid to use fields of your super class; those are private implementation details of that class. Child classes should not care about them. Instead, you could call the method from the super class.
On the other hand, you should strive for making your fields final. That makes a lot of things much easier.
When overriding methods ... use the #Override annotation!
Finally: a constructor is a bad place to create your "test data". In other words: your main method is to place to create that array of employees; and then you just pass that into your Company constructor. You want to clearly separate your "real business logic" from that stuff that mainly exists to test that "business logic".
StackPeople, I have a question. What statement could help me implement the right class before inserting it to the ArrayList. I have declared Nurse and Pilot which are Employees objects.
I want each implementation of my class ArrEmp to store different Employees objects
example: arrEmpNurses, arrEmpPilots,... after my class gets an example in the constructor
What statement helps?? Or should I re think the problem.
Thanks for your help.
THE PROBLEM IS TO FILL THE ARRAY WITH THE RIGHT CLASS (IT WILL READ FROM PLAIN TEXT AND IT NEWS TO BE NOTIFIED WhAT CLASS TO IMPLEMENT TO ADD IT)
"This code compiles, just copy paste."
import java.util.*;
public class ArrEmp {
String[][] data={ {"E1"}, {"Maria"}, {"E2"}, {"John"} }; //Data
Employee x;
static Nurse nancy= new Nurse("01","Nancy");//this are just examples
static Pilot peter= new Pilot("02","Peter");//so the arrayEmp knows what type of employee create
ArrayList arr;
public ArrEmp(Employee x){
this.x=x;
arr= new ArrayList();
fillList();//with data array
}
public void fillList(){// I would like to fill the List with Nurses. How could i do it?
//for( String[] param: data )
//arr.add( ) //insert helpfull statement here
//the goal is to have an array of Pilot and another of Nurses
}
public static void main(String[] args) {
ArrEmp arr1= new ArrEmp( nancy );
ArrEmp arr2= new ArrEmp( peter );
}
public static class Employee {
String cod;
public Employee(String cod){
this.cod=cod;
}
}
public static class Nurse extends Employee{
String name;
public Nurse(String ... para){
super(para[0]);
this.name=para[1];
}
}
public static class Pilot extends Employee{
String name;
public Pilot(String ... para){
super(para[0]);
this.name=para[1];
}
}
}
I asked the question this way because data is actually read from Disk and ArrEmp has no idea what Employee he is reading. i need to provide an example so it builds the right employee and then insert it into the array. so new ArrEmp( nancy ) reads the file and builds Nurses and store them but new ArrEmp( nancy ) reads a file and loads Pilots on it.
EDIT SOLUTION: ESCENTIALLY I WILL CREATE A GENERIC ARRAYLIST EXTENDS EMPLOYEE, and extending classes for each Emlployee object...
Why not use generics? See: Java generics - ArrayList initialization
Essentially use
ArrayList<Nurse>
Instead of ArrayEmp(Nancy) to say it will only contain Nurses, then the language will take care of enforcing it.
public static class Employee {
String name;
int ID = 0;
public Employee(String name){
this.name = name;
}
}
Just use ID's to denote the differentiation between all of them? You can create an ENUM and fill in legible names for differentiating between different objects. It's faster then string comparing and using instanceOf.
public static class Pilot extends Employee{
int ID = 1;
public Pilot(String name){
this.name = name;
}
}
EDIT:
public ArrEmp(Employee x){
if (x.ID == 1) // add to the list you want
else if (x.ID == 2) // add to list you want
....
}
I have this issue with my code.
I create a class Employee with two instance variables:
private String name, department;
And afterwards I create another class called Tradesman whichc is an extension of Employee, but with one extra instance variable:
private String trade;
Now what I did is I created a print() method that will: A) in Employee class, print the name and department. B) same method used in Employee, will be created in Tradesman (thus overriding it) that will print extra one element which is the trade. Now the thing is that I create another class called Staff which will contain an array of type Object of some elements, and I have to implement a hire() method, fire() method and a put() method which will print the entire array. Everything is cool and wicked up till the moment of printing. I'm struggling with how to print it, since I have print() method for each class but it must be dependedn on the type... If i cast the method to Employee I will lose the trade element of Tradesman Class, ex:
void put(){
for (Object a:objArray){
((Employee)a).print();
}
}
Which is WRONG. Cause if I hire a Tradesman, this method won't print the Trade. How to deal with this problem? Thanks in advance! Cheers ^^
"Cause if I hire a Tradesman, this method won't print the Trade"
You're wrong, it will. If Employee is actually a Tradesman, calling print() will call Tradesman.print(). If it's overriden, then the overriding method will be called. If all your array objects are Employee, just use an Employee[] instead of Object[] so you don't have to do that useless casting.
"I want to implement an array of both Tradesman and Employee... One array that will contain both, Tradesman and Employee combined."
Employee[] will hold both since a Tradesman is an Employee. Also in Java I suggest you work with a List (List<Employee> in your case), it's more manageable than an array.
Even if you cast a Tradesman to Employee the underlying object will still be of type Tradesman and use the overridden print method.
try this
import java.util.ArrayList;
class Employee {
String name,department;
public Employee(String name, String department) {
this.name = name;
this.department = department;
}
public void print() {
System.out.println("Name: " + this.name);
System.out.println("Department: " + this.department);
}
}
class Tradesman extends Employee {
String trade;
public Tradesman(String name, String department, String trade) {
super(name,department);
this.trade = trade;
}
public void print() {
super.print();
System.out.println("Trade: " + this.trade);
}
}
class Staff {
ArrayList<Employee> empArray = new ArrayList<Employee>();
public void put() {
for(Employee emp : empArray) {
emp.print();
}
}
public static void main(String[] arg) {
Staff s = new Staff();
s.empArray.add(new Employee("John","Sales"));
s.empArray.add(new Tradesman("Jacob","Sales","Computers"));
s.put();
}
}
I have an Object named Person(name, surname, age)
This Object is populated with values from a local file.
But i want to keep this object visible through the app since there is a GUI for adding new values to this.
I was trying to put an Interface like this but doesn't work
public interface MyInterface{
public List<Person> myPersonObj = new ArrayList<Person>();
}
and to call it in app like MyInterface.myPersonObj
Can someone help me?
Thanks
You have to declare the variable static, e.g.
public static (final) List<Person> persons = new ArrayList();
For more information, read about the Singelton Pattern
Because it's in an interface it will automatically be final (read-only), thus you probably want to put it in a class instead:
public class AnyClass{
public static List<Person> myPersonObj = new ArrayList<Person>();
}
Then you can do:
AnyClass.myPersonObj
to access it.
make the list static inside the class where you populate it.
class Populate{
public static List<Person> myPersonObj;
public static void setMyPersonObj(List<Person> inst){
myPersonObj =inst;
}
public static List<Person> getMyPersonObj(){
if(MyPersonObj!=null){
return myPersonObj;
}
else {
return new ArrayList<Person>();
}
}
//populate it
}
class SomeOther {
public static void someMethod(){
Populate.getMyPersonObj();
}
}