My assignment:
Code a class called SeniorWorker which inherits from Employee class, in addition to name, salary, and overtimePay, it adds a double type data called meritPay which is calculated as 10% of the salary. It overrides earning() and toString methods to compute the total salary of SeniorWorker and return proper data of SeniorWorker, respectively.
Clarification: The assignment lets us use some example code from the book (Employee,RegularWorker,Manager, SeniorManager. java). My problem is that the SeniorWorker class inherits from the Employee class all those variable however the Employee class only includes the name variable and the rest of the variables except the meritPay are in the RegularWorker Class that why I'm wondering if I could inherit from both the Employee class and RegularWorker or do I need to do something else?
Code:
public class Employee {
private String name;
// Constructor
public Employee(String name ) {
this.name = name;
}
public String getName()
{ return name; }
public double earnings(){return 0.0;}
}
public class RegularWorker extends Employee {
protected double salary, overtimePay;
public RegularWorker( String name, double salary, double overtimePay) {
super( name ); // call superclass constructor
this.salary = salary;
this.overtimePay = overtimePay;
}
public double earnings() { return salary + overtimePay; } //override the method to return salary
public String toString() { //override the method to print the name
return "Regular worker: " + getName();
}
}
My Class:
So far i've just resorted to inheriting from the regularworker class(and it works) , however the assignment says i should inherit from employee class.
public class SeniorWorker extends RegularWorker {
public double meritPay;
public SeniorWorker(String name, double salary,double overtimePay, double meritPay)
{
super(name,salary,overtimePay);
this.meritPay = meritPay;
}
public double getMeritPay() {
return meritPay;
}
public void calculateMeritPay(){
meritPay = 0.10 * salary;
}
public double earnings() { return salary + overtimePay + meritPay; } //override the method to return salary
public String toString() { //override the method to print the name
return "Senior Worker: " + getName();
}
}
No, in java you can only inherit from one class. However, that class can inherit from another, and so on. You can extend multiple interfaces, which in java 8 could contain default method implementations (which could be default getters that return a predetermined value for the encapsulated attributes).
However, inheritance should only really be used for code sharing, and interfaces should only really be used for polymorphism.
Having said that, in your example, your RegularWorker is an Employee, so your SeniorWorker is a RegularWorker and is an Employee. Therefore, your SeniorWorker is inheriting (is extended from) Employee, as your assignment requests.
But, if you think about it, how can a senior worker also be a regular worker? They're not regular, they're senior. They may have been regular at one point in their career, but now they're senior, and not regular at all, despite having some stuff in common with regular employees. If you push the stuff from regularemployee up to employee, and have two descendants of employee, regular and senior, then you'll have sorted this mess out and probably earned extra points for being clever.
Related
I am new to Java. I have a problem to solve, but I don't quite understand how constructors work. I understand how to create a superclass and a subclass but I don't understand the constuctors within them (or how they actually work - I have done rediculous amounts of research on constructors, but it's just not making much sense).
I am trying to write a program that creates a superclass called Employees. This Employee class has instance variables employeeId (which is an integer) and employeeName (which is a String).
The subclass is called Manager. The Manager subclass has an instance variable called employeeTitle (which is a String). It also has a method with the name of managerDetails(). ManagerDetails() is supposed to display the employeeId, employeeName, and the employeeTitle.
This is what I have so far:
package tryingoutjava;
public class TryingOutJava {
class Employee {
int employeeId;
String employeeName;
void Employee() {
}
}
class Manager extends Employee {
String employeeTitle;
void managerDetails() {
}
}
public static void main(String[] args) {
}
}
I am very confused on how to set up the constructors for the superclass and the subclass, or even what a constructor really looks like. I've seen examples all over the internet, but no one actually highlights the actual part that is the constructor, or how everything is linked visually, which is what helps me learn.
I guess I'm also having issues with understanding how to set up a method that calls on an object. If anyone has the time to help, it would greatly be appreciated. Thanks!
I guess you want something like this. Be noted, that it is a good idea to separate classes one-per-file in this case, as they are separate entities here. It is a good idea to limit data access to entity fields, as such using encapsulation.
Employee.java:
package tryingoutjava;
public class Employee {
// Protected access because we want it in Manager
protected int employeeId;
protected String employeeName;
public Employee(int employeeId, String employeeName) {
this.employeeId = employeeId;
this.employeeName = employeeName;
}
}
Manager.java:
package tryingoutjava;
public class Manager extends Employee {
private String employeeTitle;
public Manager(String employeeTitle, int employeeId, String employeeName) {
// Use super to invoke Employee constructor
super(employeeId, employeeName);
this.employeeTitle = employeeTitle;
}
// Just create a simple string describing manager
#Override
public String toString() {
return "Manager{" +
"employeeTitle='" + employeeTitle +
"employeeId=" + employeeId +
", employeeName='" + employeeName + '\'' +
'}';
}
}
Application.java:
package tryingoutjava;
public class Application {
// Example of construction plus printing of Manager data
public static void main(String[] args) {
Employee davie = new Employee(1, "Dave The Cable Guy");
Manager tom = new Manager("CFO", 2, "Tomas");
System.out.println(tom.toString());
}
}
Constructors (most often than not) just delegate construction of parent through super invocation. While there are other techniques, like Builder pattern, this is the most basic and understandable approach. There are several other ways to do this, but this should get you started, hope it helps!
Purpose of Constructor
constructor is a method like other method but it is called when instantiate (or create a object from your class) for initialize your object for first use or later use. for example a class like Student must created (instantiated) when we give it name and family name for example. Without them, create a Student is not good because maybe we forget to give it proper name and use it incorrectly. constructor forces us to provide minimum things needed for instantiating objects from classes.
Constructor implementation in inheritance
About inheritance, it is different. When you want to create a Student which is a Human (extends Human) you must first create Human inside your Student and set special feature for your Student like ID which is not for Human (Human has name and etc). so when you create a Student with constructor, the super constructor (for Human) is called too.
What do we do in constructor
as I mentioned, we provide default value for our properties which must set them before creating and using object. (for using them properly) every subclass call super class constructor implicitly with super() but if super class doesn't have any default constructor (constructor with no argument) you must explicitly say super(...) at the first lien of subclass constructor (otherwise compile error)
What is the program steps when using constructor (Advanced)
super class static constructor and static variable (read by self if you want to know more about things I say here)
subclass class static constructor and static variable
super class variable and block constructor
super class constructors
sub class variable and block constructor
sub class constructors
I only mentioned 4 & 6.
I try to explain completely. My English is not good. I'm sorry.
If you know how a method works, then you know how a constructor works. The constructor is simply a special method that allows you to execute some code before the object is created.
Person p = new Person("Bob", 25); // Calls constructor Person(String name, int age)
Then in the constructor you can do things like assign initial values to any instance variables.
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
If the class is a subclass you need to call a constructor of the parent class before the object is created unless the parent class has a constructor with no parameter in which case java can call it for you if you don't specify anything. Here Worker extends Person.
private String occupation;
public Worker(String name, int age, String occupation) {
super(name, age) // Calls constructor Person(String name, int age)
this.occupation = occupation;
}
I guess you can achieve what you want in a single file via the code snippet below:
You can copy paste it in your code and it should work.
You can see how the constructor of parent class is being called by the help of super() and also the methods. Here I have used methods like getEmployeeTitle() which should help you get an overview on how to write methods. I have also overridden the toString() method so that you can understand how to override Object class' useful methods like toString().
Note : Although I have created all the classes in one code snippet for the sake of simplicity , but it is highly recommended that you create a separate file for each of these classes.
class Employee {
int employeeId;
String employeeName;
Employee(int employeeId, String employeeName) {
this.employeeId = employeeId;
this.employeeName = employeeName;
}
}
class Manager extends Employee {
private String employeeTitle;
Manager(int employeeId, String employeeName, String employeeTitle) {
super(employeeId, employeeName);
this.employeeTitle = employeeTitle;
}
public String getEmployeeTitle() {
return employeeTitle;
}
#Override
public String toString() {
return ("employeeId: " + employeeId + ", employeeName: " + employeeName + ", employeeTitle" + employeeTitle);
}
}
public class TryingOutJava {
public static void main(String[] args) {
Manager manager = new Manager(007, "John Doe", " Sr. Manager");
System.out.println(manager);
System.out.println(manager.getEmployeeTitle());
}
}
public class ClassA_V01 {
private String name;
private int age;
// getter and setter
}
public class ClassA_V02 {
private String name;
private int age;
private int gender;
// getter and setter
}
public static void main(String[] args) {
SomeClass classA = new ClassA_V01();
classA.setName("myName);
classA.setAge(99);
performLogic(classA);
// OR
SomeClass classA = new ClassA_V02();
classA.setName("myName);
classA.setAge(99);
classA.setAge(1);
performLogic(classA);
}
public void performLogic(SomeClass classA) {
// do something
}
For strategy pattern to work, both classes must implement the same methods defined in the interface. But what if the classes need to have different fields and methods?
In my example, ClassA_V01 and ClassA_V02 are the same class except that one has more attribute "gender"
How does one implement the above such that classA can be equals to either ClassA_V01() or ClassA_V02?
"...For strategy pattern to work, both classes must implement the same methods defined in the interface. But what if the classes need to have different fields and methods?..." really this is not a criteria for strategy pattern.
Strategy pattern's intent is to identify and make family of algorithms interchangeable. If you read the pattern's documentation carefully, Strategy can be used when many related classes differ only in their behavior.
Appropriate decomposition is the key for better (extendable) design. A typical (but primitive) solution to Employee assignment, sub-classing tempEmp and permanentEmp types will put us in trouble and will not allow temp employee to become permanent in its life time (which has no meaning in real terms). This happens because we miss an important point- each employees employeeness is not different, they are all same type of employees with different pay policies. (same logic can be extended for Leave policy and so on)
This becomes simple if all types of employees have Salary computation based on same components (same state). But your question is what if TempEmployee gets only basicPay whereas PermanentEmployee gets basicPay as well as travelAllowance (additional attribute which is not present for TempEmp). This can be modeled by a combination of simple inheritance hierarchy along with strategy taking care of computation algorithm dependent upon Employee's (aka. Context) attribute (age)
public class Employee {
//name and id
private PayPackage payPackage;
private int age;
PayPackage strategy;
public double computeSalary() {
return payPackage.computePay(age);
}
//get/setPayPackage(...)
}
public abstract class PayPackage {
private double basicPay;
abstract public double computePay(int age);
protected double getBasicPay(){
return basicPay;
}
}
public class TempPayPackage extends PayPackage{
#Override
public double computePay(int age) {
double veteranAllowance = 0;
if (age > 40) {
veteranAllowance = 2000.00;
}
return getBasicPay() + veteranAllowance;
}
}
public class PermanentPayPackage extends PayPackage{
private double travelAllowance;
#Override
public double computePay(int age) {
double veteranAllowance = 0;
if (age > 40) {
veteranAllowance = 5000.00;
}
return getBasicPay() + travelAllowance + veteranAllowance;
}
}
Important thing to remember is Design patterns never work alone or as an alternative, they work hand in hand with Object oriented code and other patterns.
public void setName (String n){}
public void setAfm (String a){}
These are the Superclass methods i need to call.
SalariedEmployee (){
name = super.setName(String n);
afm = super.setAfm(String a);
salary = payment();
And thats the constructor in the subclass. How can i call the methods properly. I don't want to use any parameters in SalariedEmployee, i want to set the name and afm with the superclass methods. But my methods are void. So i guess i have to change that right ? Or am I missing something else?
Thanks in advance!
EDIT : You can also use setters. The "super" keyword is mandatory only if you want to call a method from the superclass that you have overridden in the subclass.
You should use constructors to set initial values but using setters is a possible solution too :
class Employee {
String name;
String afm;
public Employee() {
}
public Employee(String name, String afm) {
super();
this.name = name;
this.afm = afm;
}
public void setName(String name) {
this.name = name;
}
public void setAfm(String afm) {
this.afm = afm;
}
}
class SalariedEmployee extends Employee {
//Using constructors
public SalariedEmployee(String name, String afm) {
super(name, afm);
salary = payment();
}
//using setters
public SalariedEmployee() {
setAfm("afm");
setName("name");
salary = payment();
}
}
Also a setter method like 'setName' should be void because you don't expect it to return anything unlike a getter method like 'getName' for example.
There are two cases when you want to call a super method. The first case is that the method was not overriden by the subclass. If that is the case, you can call those methods simply by calling
setName("Dick Aceman");
or
setAtf("Acebook");
It is more descriptive if you call them like this:
this.setName("Dick Aceman");
this.setAtf("Acebook");
The bulletproof way to call them is this:
super.setName("Dick Aceman");
super.setAtf("Acebook");
This last one works even if the methods were overriden, but in general it is considered to be too descriptive, so this kind of method call should be used only when there is no alternative. Note, that since your methods are public, they are inherited by subclasses.
The problems with your try were that:
you tried to assign the return value of the methods to variables, when the methods do not return values
you declared the type at method call, which is invalid
you used the undefined variables of a and n
You should watch a few tutorial videos, you will get the basics then. After you watch such a video or two, you should return to this answer.
I don't understand accessor methods and I'm stuck with creating setAge, getAge and getName.
This is the question:
Add three accessor methods, setAge, getAge and getName. These methods should set and get the values of the corresponding instance variables.
public class Player {
protected int age;
protected String name;
public Player(String namArg) {
namArg = name;
age = 15;
}
}
An accessor method is used to return the value of a private or protected field. It follows a naming scheme prefixing the word "get" to the start of the method name. For example let's add accessor methods for name:
class Player{
protected name
//Accessor for name
public String getName()
{
return this.name;
}
}
you can access the value of protected name through the object such as:
Player ball = new Player()
System.out.println(ball.getName())
A mutator method is used to set a value of a private field. It follows a naming scheme prefixing the word "set" to the start of the method name. For example, let's add mutator fields for name:
//Mutator for name
public void setName(String name)
{
this.name= name;
}
now we can set the players name using:
ball.setName('David');
Your instance variables are age and name. Your setter methods are void and set your passed arguments to the corresponding variable. Your getters are not void and return the appropriate variables.
Try this and come back with questions.
public class Player {
protected int age;
protected String name;
// mutator methods
public void setAge(String a) {
age = a;
}
public void setName(String n) {
name = n;
}
// accessor method
public string getAge() {
return age ;
}
public string getName() {
return name;
}
}
setAbcd methods are mutator methods which you use to set your protected data fields.
getAbcd methods are accessor methods which you use to return values of the data fields, as they are usually private and not available outside the class.
e.g
public void getvariableName() {
return variableName;
}
Answer for: I don't understand accessor methods
here is the thing:
why do we need accessor methods? Encapsulation !!!
Why do we need encapsulation?
1) Imagine you (programmer#1) gonna write those setAge, getAge and getName methods.
I am programmer#2. I most probably cant access age and name directly. So I have yo use your public accessor methods setAge, getAge and getName. This is to save your code and variables from mess. Cuz u cant trust all coders.
2) In setAge method u can provide VALIDATION
random evil programmer: ya I wanna make age equal to 234 so ur program results gonna crush hahaha
u: nah I gonna add validation condition into my setAge method so u can only make age equal from 0 to 90(whatever u want)
This is the most popular reason why we use accessor methods.
Code explanation:
setAge explanation( this is just to get main idea)
public void setAge(int ageInput) {
if ((ageInput > 10) && (ageInput <90))
{age = a;}}
Random evil programmer sends ageInput into your public method.
First of all, it checks if age value is correct. If yes, age instance(object) variable will become ageInput. If no, nothing will happen and your variables wont be messed up.
GetAge: it just returns current age value. Nothing fancy.
let me know if you have more questions ;) Best of luck to you.
I have a facade engine with a method
getOwner()
I also have another class called Car and another caller Owner. Car class also has a getOwner() method while the Owner class contains the name, the cost of the car and the budget of the owner.
So I have a method to initialize the engine and this calls the constructor in the newCARengine class.
public static void iniEngine(String name, int cost) {
model = new newCARengine(name, cost);
}
Composition. The engine class has a car, and the car class has an owner. For me to successfully call the getOwner() method I need to use instance variables (class level variable) to hold a reference to the other object in order to call that method from that object.
MY ENGINE CLASS: [below]
public class engine{
private String name;
private int cost;
public Car car;
public engine(String name, int cost){
this.name = name;
this.cost = cost;
}
public Owner getOwner(){
return car.getOwner();
}
}
I'm referencing the Car class by using an instance variable for that class "public Car car;" which then allows me to use "car.getOwner();" method.
MY CAR CLASS: [below]
public class Car{
public Owner owner //instance variable to reference the owner class
public Owner getOwner(){
return owner;
}
}
Now i'm ready to go to the Owner class where the Owner object is created.
MY OWNER CLASS: [below]
public class Owner{
private String name;
private int cost;
private int budget;
public Owner (String name, int cost){
this.name = name;
this.cost = cost;
}
public Owner (String name, int cost, int budget){
this.name = name;
this.cost = cost;
this.budget = budget;
}
public String getName(){return name;}
public int getCost(){return cost;}
public int getBudget(){return budget;}
}
Now I am doing something wrong as when I run the iniEngine() method, I get a nullpointer exception and this I belive is a result of the object not being created. The error is generated from here:
return car.getOwner(); //from the ENGINE CLASS
I need to return an object as a result of my engine class. but the object is not getting created. Any assistance would be appreciated.
I reviewed your code several times. I don't understand where you associate an owner to a car.
This is what causes the NullPointerException
I suggest you provide a CTOR to Car that gets Owner as parameter and in addition, consider having a setCar method.
Consider using the following code for Car:
public class Car{
public class Car(Owner owner) {
this.owner = owner;
}
private Owner owner //instance variable to reference the owner class
public void setOwner(Owner owner) {
this.owner = owner;
}
public Owner getOwner(){
return owner;
}
}
Style note: in Engine, car should probably also be private, just like the other fields, with either a setter, or a constructor argument.
It seems like some of the fields are not getting set. One debugging "trick" I use in similar cases is to temporarily make the fields final, and see what the compiler complains about. For example, if anybody is setting engine.car, it would complain. In this case, that is a good thing - it should be complaining! And, if nobody is setting engine.car, that's a red flag as to where the NPE is coming from.
Alternatively, if you do have setters/getters, put breakpoints in them (or, if you prefer, add System.out.prints) to verify that they are getting called. Or, temporarily rename them (I add "xxx" to the beginning) to verify that the compiler complains, proving that somebody is calling them.
I never instantiated the objects and only delcared the variables.
By changing the constructor to
public Engine(String name, int cost) {
car = new Car(new Owner(name, cost));
}
This created the objects successfully which in turn allowed me to call the getOwner() method and not get any NullPointerExceptions. Must have missed this part somehow.