Printing an Array that Includes Inheritance members? - java

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();
}
}

Related

How to use own method on ArrayList in Java?

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!

ArrayList of class as parameter

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
....
}

How can I iterate through a TreeMap and use reflection to get a subclass name?

Suppose I had the following abstract class and two subclasses:
public abstract class Contact {
private String name;
public void showDetails() {
System.out.println(name);
}
}
public class Personal extends Contact {
private String relationship;
// #override
public void showDetails() {
System.out.println(name);
System.out.println(relationship);
}
}
public class Business extends Contact {
private String company;
// #override
public void showDetails() {
System.out.println(name);
System.out.println(company);
}
}
Also suppose that I have a TreeMap containing integers as keys and either Business objects or Personal objects as values:
Map<Integer, Contact> masterList = new TreeMap<Integer, Contact>();
masterList.put(1, bContact1);
masterList.put(2, bContact2);
masterList.put(3, pContact1);
masterList.put(4, pContact2);
Is it possible to iterate through the TreeMap AND use reflection to see what subclass each object belongs to, in order to use the correct overriding method?
For example, key 1 is paired with bContact1, which is a Business object. I want to use the showDetails() method from the Business subclass for this particular value.
I can iterate through the map just fine, but I'm having trouble with the reflection part. Any help is appreciated!
You don't need reflection, you need polymorphism. Just call the method on the object, Java will do the rest to invoke the proper implementation.
Contact contactRef = masterList.get(2);
contactRef.showDetails(); // overriden method invoked if it exists, inherited otherwise

Cannot make a static reference to the non-static method

I have searched for this problem and found many answers regarding it but however i did not understand them , i would a clarification regarding my own code so hopefully it will makes sense
i am trying to call the PrintList method in the main method
but i get this error
Cannot make a static reference to the non-static method PrintList() from the type Stack
if i change the modifier of PrintList to static , it ruins the whole code.
can anyone help me fix this issue please?
Thanks
public class Stack<Item> {
public int N; // size of the stack
public Node<Item> first; // top of stack
public Node<Item> last; // top of stack
// helper linked list class
private static class Node<Item> {
private Item item;
private Node<Item> next;
}
public Stack() {
first = null;
last = null;
N = 0;
}
public void PrintList() {
Node<Item> current;
current = first;
while (current.next != null) {
System.out.println(current.item);
current = current.next;
}
}
public static void main(String[] args) {
// Declare the stack
Stack<String> s = new Stack<String>();
s.push("Bob");
s.push("Mary");
s.push("David");
s.InsertBegin("George");
System.out.println("First item: " + s.peek());
Object current;
PrintList(); // what is wrong here?
}
}
The problem is that you are not specifying the instance that PrintList is to be called on. To fix that, change this:
PrintList(); // what is wrong here?
to this:
s.PrintList();
What you really need is to understand exactly what static and non-static actually mean.
First, some background. Apologies if some of this is already familiar to you. Java is an object oriented language, you create a class to act as a template for a specific type of object, defining what attributes (variables) that it has, and how it behaves (methods). These attributes and behaviours belong to objects of that class:
public class Person {
private String forename;
private String surname;
public Person(String forename, String surname) {
this.forename = forename;
this.surname = surname;
}
public String getFullName() {
return forename + " " + surname;
}
public static void main(String[] args) {
Person john = new Person("John", "Doe");
}
}
The above code defines a template for creating objects of the type Person, each having a forename and a surname, both of the type String. It also defines a behaviour that allows you to get a Person's full name using the getFullName() method.
Both forename and surname, as well as getFullName() are examples of non-static fields/methods. That is, they belong to a specific Person object. Importantly: none of these can exist without a Person object being created first. In this case we have a Person object called john which has a forename of "John" and a surname of "Doe". If we were to call john's getFullName() method:
john.getFullName();
Then we'd get "John Doe" back.
The opposite of this is static. Static things do not belong to an object, instead, they belong to a class.
public class Person {
private String forename;
private String surname;
private static String species = "Homo sapiens";
public Person(String forename, String surname) {
this.forename = forename;
this.surname = surname;
}
public String getFullName() {
return forename + " " + surname;
}
public static void main(String[] args) {
Person john = new Person("John", "Doe");
}
}
Here the String species doesn't belong to john, it belongs to Person. Static methods and variables don't need an object in order to exist, they always* exist. You access it by using the class itself as a reference, like this:
Person.species;
In your example, you have defined a method PrintList() as a behaviour of objects of the Stack<Item> class. The problem is that you're inside the main method, which is static. This means that you aren't in the 'context' of an object (because main belongs to Stack<Item>, not objects of the type Stack<Item>) when you're trying to call the PrintList() method. When you're inside a static method, in order to call a non-static method or access a non-static attribute, you must do so using a reference to an object of the class that owns it. In your case, you already have this reference in the form of s, so you can call your PrintList() method like so:
s.PrintList();
NB: Conventionally in Java we use camelCase for method names, so it really should be printList().
When I first started to learn Java, I found the concept of static very difficult to wrap my head around - because I hadn't learned to think in an object-oriented way yet. When the penny drops, you'll wonder why you ever struggled with it. Hopefully this will help you get closer towards that penny-drop moment!
*As long as the class is loaded and it's not a compile-time constant (but you don't need to worry about those yet).
You can call static methods like this:
ClassName.methodToCall();
You can call non-static methods like this:
ClassName classInstance = new ClassName();
classInstance.methodToCall();
Since your method PrintList() is non-static as it should be in this case, you should call it on an instance.

Returning data from a sub-class

I have a subclass "shopStaff" within class "staff". I have a meathod getPerson which I need to send the data set in staff and the data set in shopStaff as a single string.
This is my code
// in staff
public String getPerson()
{
return format(name) + format(yearJoined);
}
// in shopStaff
public String getPerson()
{
super.getPerson();
return format(department);
}
however, when I invoke the getPerson meathod in the subclass it only returns the department information, not the name and yearjoined (that I only set in the superclass.
I thought when I used the super. meathod it would return everything from the class above in the hierarchy. Is this not the case? If not could anyone tell me how I access the information set in the superclass?
Thanks
CJ
When you call:
super.getPerson();
The return is discarded as it is not stored anywhere. You'd want to do this:
//in shopStaff
public String getPerson() {
return super.getPerson() + format(department);
}
Your return value from super.getPerson() is not returned with the return statement in your current getPerson() method. It is just lost in your code.
You need to change your shopStaff method to return the super class values with your subclass return statement: -
public String getPerson()
{
return super.getPerson() + format(department);
}
public String getPerson()
{
String fromSuper=super.getPerson();
return fromSuper + format(department);
}
Just calling super will not get data unless you read and use it in subclass.
May be something like this will work:
public String getPerson()
{
String person = super.getPerson();
return person+format(department);
}

Categories