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.
Related
I want to program a factory that creates two types of People which are "Employee" and "Entrepreneur". They both share the same basic "Person" attributes but they also implements their unique ones.
The problem is that if i want to return a method or an attribute that is not declared in the "Person" abstract class the program doesn't find it (since obviously I'm generating an object that is type "Person" and not specifically "Employee" or "Entrepreneur" ).
How do i tackle this problem?
This is the Demo class
public class Demo{
public static void main(String[] args){
PersonFactory pf = new PersonFactory();
Person p1 = pf.getPerson("Employee");
p1.presentation();
System.out.println(p1.getComplanyName());
}
}
This is the abstract class
public abstract class Person{
String name;
String surname;
abstract void presentation();
}
Those are the two concrete classes that extend Person
public class Entre extends Person{
int licenseNumber;
#Override
public void presentation(){
System.out.println("hi i'm an Entrepreneur");
}
public int licenseNumber(){
return licenseNumber;
}
}
public class Empl extends Person{
String companyName;
#Override
public void presentation(){
System.out.println("hi i'm an employee");
}
public String getCompanyName(){
return companyName;
}
}
Finally the Factory
public class PersonFactory{
public Person getPerson(String type){
if(type.equalsIgnoreCase("ENTREPRENEUR")){
return new Entre();
}
else if(type.equalsIgnoreCase("Employee")){
return new Empl();
}
return null;
}
}
Today I had test in OOP and I was given the following task to code:
Imagine you have two classes: Employee (which represents being an employee) and Ninja (which represents being a Ninja). An Employee has both state and behaviour; a Ninja has only behavior. You need to represent an employee who is also a ninja (a common problem in the real world). By creating only one interface and only one class (NinjaEmployee), show how you can do this without having to copy method implementation code from either of the original classes. Test your code in main method
I did not really understand the problem well, but this is the solution I came with (I know it's not what was asked):
I created 4 classes except main. As Employee has state and behaviour I came up with this code:
public class Employee {
private int ID;
private String Name;
private double salary;
public Employee(int ID, String Name, double salary) {
this.ID = ID;
this.Name = Name;
this.salary = salary;
}
public int getID() {
return ID;
}
public void setID(int ID) {
this.ID = ID;
}
public String getName() {
return Name;
}
public void setName(String Name) {
this.Name = Name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public void startWorking() {
System.out.println("Started Working");
}
}
Class ninja has only behaviour:
public class Ninja {
public Ninja(){}
public void moveNinja(){
System.out.println("Ninja moved");
}
}
Class NinjaEmployee:
public class NinjaEmployee extends Employee implements MyInterface {
public NinjaEmployee(int ID, String Name, double salary) {
super(ID, Name, salary);
}
public void moveNinja() {
System.out.println("Ninja Moved");
}
}
Interface which does not make sense in my code:
public interface MyInterface {
public void moveNinja();
public void startWorking();
}
Main class:
public static void main(String[] args){
MyInterface em = new NinjaEmployee(123,"Sandro",1000000);
em.moveNinja();
em.startWorking();
}
My question is following:
1) Specifically/Technically what was asked in test?
2) What would be correct approach/code for given problem?
Nice question.
The key point of the question is:
we should use one interface.
Ninja class should have some methods (not attributes).
So we should try to use these key point.
I provide a class diagram below:
First of all: We have Employee class and implement it like other simple classes. It has some implemented attributes and classes.
Secondly: We have an Interface named Ninja_Interface that have some method declarations about ninja. (moveNinja1 and moveNinja2)
Thirdly: Ninja Class that implemented (or Realized) Nijna_Interface and have some implementation of any method declarations in Ninja_Interface.
Fourthly: the NinjaEmployee class. It inherited from Employee. So it has all Employee's attributes and methods. Also it implements Ninja_Interface. So it should implements all Ninja_Interface methods declarations. On the other hand, NinjaEmployee have an instance of Ninja (notice that Ninja class implements all Ninja_Interface methods). So, In Ninja_Employee class, in implementation of Ninja_Interface methods, we can use Ninja instance methods to call.
For example some parts of NinjaEmployee is like below code:
private Ninja ninja=new Ninja();
public void moveNinja1()
{
ninja.moveNinja1();
}
public void moveNinja2()
{
ninja.moveNinja2();
}
Main question is: why Ninja class should have only some methods?
It is because of Ninja class is just the implementations of Ninja_Interface methods and there no need to have attributes. So instances of Ninja class are the same. So we can declare Ninja attribute in NinjaEmployee as static attribute.
Finally: we can add some attributes of ninja into NinjaEmployee class too.
I don't know correct answer (task is kinda not very strictly defined, there is some unclear moments), but i would do something like this:
public interface IAmNinja {
public void moveNinja();
}
public interface IAmEmployer {
public void startWorking();
}
public class NinjaEmployee implements IAmNinja, IAmEmployer {
private Ninja _ninja;
private Employer _employer;
public NinjaEmployee(int ID, String Name, double salary) {
_employer = new Employer(ID, Name, salary);
_ninja = new Ninja();
}
public void moveNinja() {
_ninja.moveNinja();
}
public void startWorking() {
_employer.startWorking();
}
}
You cant create 1 object of 2 class es
You can extend class so whenever child class is instantiated it calls parent class constructor
Then You can create object of another class in that constructor
Add employees in array and add option to add employee in ninja? 1.yes or 2.no?
if yes , add to ninja..then in main method print names of ninja using for loop one by one
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!
Today I read this article about avoiding the use of instanceof.
This makes absolutely sense to me. I'm also aware of the visitor pattern.
Lets say I have the following situation:
#Entity
public abstract class Employee {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer employeeId;
private String name;
}
#Entity
public class FullTimeEmployee extends Employee {
protected Integer salary;
public Integer getSalary() {
return salary;
}
public void setSalary(Integer salary) {
this.salary = salary;
}
}
#Entity
public class PartTimeEmployee extends Employee{
protected Float hourlyWage;
public Float getHourlyWage() {
return hourlyWage;
}
public void setHourlyWage(Float hourlyWage) {
this.hourlyWage = hourlyWage;
}
}
How could I avoid using instanceof when calling a method like this?
public void convertEmployee(Employee employee) {
if (employee instanceof FullTimeEmployee) {
FullTimeEmployee fullTimeEmployee = (FullTimeEmployee) employee;
calcSalaray(fullTimeEmployee);
} else if (employee instanceof PartTimeEmployee) {
PartTimeEmployee partTimeEmployee = (PartTimeEmployee) employee;
calcHourlywage(partTimeEmployee);
}
}
Here is a simple example using the visitor pattern. The fact that your classes are entities is irrelevant. What matters is that the base class has a fixed, well-known number of subclasses.
Let's start with the abstract class:
public abstract class Employee {
public abstract void accept(EmployeeVisitor visitor);
}
It contains an accept() method taking a visitor as argument. Every subclass must override this method.
Now the two subclasses, each having a distinct set of fields and methods:
public class FrenchEmployee extends Employee {
private int eiffelTowerVisits;
#Override
public void accept(EmployeeVisitor visitor) {
visitor.visit(this);
}
public int getEiffelTowerVisits() {
return eiffelTowerVisits;
}
}
public class EnglishEmployee extends Employee {
private int towerBridgeVisits;
#Override
public void accept(EmployeeVisitor visitor) {
visitor.visit(this);
}
public int getTowerBridgeVisits() {
return towerBridgeVisits;
}
}
What is this visitor? It's an interface that does something specific for each subclass:
public interface EmployeeVisitor {
void visit(EnglishEmployee employee);
void visit(FrenchEmployee employee);
}
And here is an example of it usage, compared to the usage of instanceof:
public class EmployeeService {
public void displayEmployeeWithUglyInstanceof(Employee employee) {
if (employee instanceof EnglishEmployee) {
EnglishEmployee english = (EnglishEmployee) employee;
System.out.println("An English employee that visited the tower bridge " + english.getTowerBridgeVisits() + " times");
}
else if (employee instanceof FrenchEmployee) {
FrenchEmployee french = (FrenchEmployee) employee;
System.out.println("A French employee that visited the eiffel tower " + french.getEiffelTowerVisits() + " times");
}
}
public void displayEmployeeWithVisitor(Employee employee) {
EmployeeVisitor visitor = new EmployeeVisitor() {
#Override
public void visit(EnglishEmployee employee) {
System.out.println("An English employee that visited the tower bridge " + employee.getTowerBridgeVisits() + " times");
}
#Override
public void visit(FrenchEmployee employee) {
System.out.println("A French employee that visited the eiffel tower " + employee.getEiffelTowerVisits() + " times");
}
};
employee.accept(visitor);
}
}
You might see that as overengineering, but in the case of Hibernate entities, it's actually very useful, because Hibernate uses dynamic proxies for lazy associations. So an employee might very well not be an EnglishEmployee nor a FrenchEmployee. In that case, instanceof will return false for both cases, and your code won't do anything. Whereas with the visitor, the proxy will delegate the call to the French or English employee it wraps, and everything will go smoothly.
Another advantage is that, if you add a SpanishEmployee, you will immediately see all the visitor implementations that must be modified to handle a spanish employee.
One possible trick goes:
public abstract class Employee {
// ...
FullTimeEmployee asFullTimeEmployee() {
return null;
}
}
public class FullTimeEmployee extends Employee {
// ...
#override
FullTimeEmployee asFullTimeEmployee() {
return this;
}
}
I'm a little stuck and would definitely appreciate your help. As the title says I want to store different classes on an array, which is in another class
This would be my code
The Customer class:
public class Customer {
public List<Product> products = new ArrayList<Product>();
public void addProduct(Product p){
products.add(p);
}
}
The Product class:
public abstract class Product{ }
The Ham class:
public class Jamon extends Product{
protected String marca;
protected int precio;
public Jamon(String marca,Double precio){
this.marca=marca;
this.precio=precio;
}
public void setMarca(String marca){
this.marca=marca;
}
public String getMarca(){
return marca;
}
public void setPrecio(int precio){
this.precio=precio;
}
public int getPrecio(){
return precio;
}
*/
public void comprar(){
System.out.println("Se ha comprado el jamon");
}
What I want to know is How do i store the Jamon class in the array on the Customer class, i want this because there will be multiple classes like Jamon that extend from Product. Also, if all this classes (Pepino, Jelly, etc) have precios, how can I add all the precios?
Thank you, if you have any doubt about my question please ask me (english is not my first language) Nice Day (:
Here's a small implementation of what you appear to be trying to achieve
public abstract class Product {
protected double precio;
public void setPrecio(double precio){
this.precio=precio;
}
public double getPrecio(){
return precio;
}
}
Here's another one
public class Jamon extends Product{
protected String marca;
public Jamon(String marca,Double precio){
this.marca=marca;
this.precio=precio;
}
public void setMarca(String marca){
this.marca=marca;
}
public String getMarca(){
return marca;
}
public void comprar(){
System.out.println("Se ha comprado el jamon");
}
}
Here's also this one
public class Pepino extends Product{
protected String marca;
public Pepino(String marca,Double precio){
this.marca=marca;
this.precio=precio;
}
public void setMarca(String marca){
this.marca=marca;
}
public String getMarca(){
return marca;
}
public void comprar(){
System.out.println("Se ha comprado el pepino");
}
}
And finally
import java.util.List;
import java.util.ArrayList;
public class Customer {
public List<Product> products = new ArrayList<Product>();
public void addProduct(Product p){
products.add(p);
}
public static void main(String[] args) {
Customer customer = new Customer();
Jamon jamon = new Jamon("Jabugo", 25.0);
Pepino pepino = new Pepino("Extra picante", 8.50);
Jamon negro = new Jamon("Pata Negra", 32.99);
customer.addProduct(jamon);
customer.addProduct(pepino);
customer.addProduct(negro);
for (Product product : customer.products) {
System.out.println(product.getClass());
}
}
}
Okay, so to be clear. Both Jamon and Pepino extend from Product, which means:
-Any variable (such as precio) or method (setPrecio or getPrecio) is available to them. Since its defined in the abstract class. One exception to this are the ones with private, those won't be accesible in the extending classes.
-Since customer adds a bunch of elements as Product there is no way to access the methods defined in Jamon or Pepino unless the item in the list is casted.
-It is not very common practice to declare an inner field a public variable (I'm referring to products in Customer, make a getter/setter).
-Also in your small example you seem to mix the ideas of double and int both represent numbers, but only the first has decimal point. If you are using decimal values, as it happens with precio, declare the field a double and work always with a double.
New Customer class (only storing prices, as oposed to Product, in the ArrayList)
import java.util.List;
import java.util.ArrayList;
public class Customer {
public List<Double> products = new ArrayList<Double>();
public void addProduct(Product p){
products.add(p.getPrecio());
}
public static void main(String[] args) {
Customer customer = new Customer();
Jamon jamon = new Jamon("Jabugo", 25.0);
Pepino pepino = new Pepino("Extra picante", 8.50);
Jamon negro = new Jamon("Pata Negra", 32.99);
customer.addProduct(jamon);
customer.addProduct(pepino);
customer.addProduct(negro);
for (Double productPrice : customer.products) {
System.out.println(productPrice);
}
}
}
As others have already commented, you can add an instance of any subclass of Product to an ArrayList<Product>. That you have done already.
If you want all products to have a precio, then you can define it on the abstract class Product instead of in Jamon and other subclasses. Move the declaration of the variable precio from Jamon to Product. Also move the methods getPrecio and setPrecio to Product. Create a constructor in Product to accept a precio. In constructors of subclasses such as Jamon, call super(precio) to initialize precio.
Then, you will be able to loop over all Products in your ArrayList and call the getPrecio() method to add up all precios.