I would like to model the following classes in Java:
so I came with the following code:
class Person
{
private String name;
private ing age;
public Person(String name, int age){
this.name=name;
this.age=age;
}
//set and get methods
}
class Employee
{
private String nameEmp;
private double salary;
public Employee(String nameEmp, double salary){
this.nameEmp=nameEmp;
this.salary=salary;
}
public double calcSalary(){} //should this be an abstract method?
}
class Teacher extends Person implements Employee
{
private String nameTeacher;
private int ageTeacher;
private String title; //professor or lecturer
public Teacher(String nameTeacher,int ageTeacher, String title){
super(nameTeacher,ageTeacher);
this.title=title;
}
public double calcSalary(){
if (title.equals("Professor")) salary=salary*0,30;
else if (title.equals("Lecturer")) salary=salary*0,10;
}
}
I would like to model it using interfaces, but I am not quite sure how to do it. Also the calcSalary should be an abstract method in Employee? How this can be implemented with interfaces in Java?
Thanks
No, you can't do it this way, you should go for Teacher is -> Employee is -> Person. You can't implement anything in interface! Interface can only contain methods that should be implemented by class.
You could have this:
public interface Person{
// Only abstract methods here
}
public interface Employee extends Person {
// Only abstract methods here specific to Employee
}
public class Teacher implements Employee {
//Implements the methods
}
Java 8 will allow you to place default implementations in interfaces. Until then, interfaces cannot contain implementations.
Start with Person. You had a typo there:
public class Person
{
private String name;
private int age;
public Person(String name, int age){
this.name=name;
this.age=age;
}
// set and get methods, equals, hashCode, toString,
// perhaps an id for database storage.
}
Now, some Persons are Employees; others are students, parents, prospective students, and so on. If any method of Employee has an implementation, it can't be an interface. And in any case, having nameEmp is wrong since it will duplicate the name in Person. Either you create an interface for Employee that gets mixed into the Teacher class, or you inherit from Employee.
Either:
public interface Employee {
// Currency values should use BigDecimal or BigInteger, not double.
BigDecimal salary();
// Taxpayer Identification Number (SSN) in the USA, or the equivalent outside.
String taxNumber();
}
or:
public class Employee extends Person {
private BigDecimal salary;
private String taxNumber;
public Employee(String name, int age, BigDecimal salary,
String taxNumber) {
super(name, age);
this.salary = salary;
this.taxNumber = taxNumber;
this.title = title;
}
// getters, setters, etc.
}
public class Teacher extends Employee {
private Department department;
private List<Course> courses = new ArrayList<>();
// Constructors, getters, setters, etc.
}
You should only have the salary methods in Teacher if they need a wildly-different implementation. You might want to have some sort of pay calaculator class (the Strategy pattern) in the Employee class instead. This way you can handle taxable deductions, insurance, pension plans, overtime where applicable. I didn't understand the multipliers in your original example.
public interface Person {
String getName();
void setName(String name);
int getAge();
void setAge(int age);
}
public class PersonImpl implements Person {
private String name;
private int age;
#override public String getName() { return this.name; }
#override public void setName(String name) { this.name = name; }
#override public int getAge() { return this.age; }
#override public void setAge(int age) { this.age = age; }
}
public interface Employee extends Person {
double getSalary();
void setSalary(double salary);
double calcSalary();
}
public abstract class EmployeeImpl extends PersonImpl implements Employee {
private double salary;
#override public double getSalary() { return this.salary; }
#override public void setSalary(double salary) { this.salary = salary; }
}
public class Teacher extends EmployeeImpl
#override public double calcSalary() {
if (title.equals("Professor")) salary=salary*0,30;
else if (title.equals("Lecturer")) salary=salary*0,10;
}
}
Related
I am supposed to refactor duplicated attributes in Student class. I have Student and Professor classes as below. I am really confused about how to do refactoring with attributes. Should I add a new class, or made modifications in one of the classes. If so, how? I could not understand how to proceed with this to-do.
private final String matrNr;
private final String name;
private final int age;
private int semester;
private final String email;
public Student(String name, int age, String email, String matrNr, int semester) {
this.matrNr = matrNr;
this.name = name;
this.age = age;
this.semester = semester;
this.email = email;
}
public String getEmail() {
return email;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public int getSemester() {
return semester;
}
public String getMatrNr() {
return matrNr;
}
public void increaseSemester(){
semester = semester + 1;
}
}
And the professor is a like:
private final String persNr;
private final String name;
private final int age;
private final String email;
public Professor(String name, int age, String email, String persNr) {
this.persNr = persNr;
this.name = name;
this.age = age;
this.email = email;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public String getPersNr() {
return persNr;
}
}
Thanks for any kind of helps!
Your goal is to refactor duplicated attributes in the Student and Professor classes. The way to do this is to create a parent class which defines the common attributes (like "name"), and modify Student and Professor classes to extend the common parent class. In this way, both Students and Professors can have a "name", even though you have defined "name" only once in the common parent.
Below shows how you could do this with a common "Human" parent class, how the constructors would work, and how you could define a Student-only attribute (semester).
Here is a simple version a common Human class:
common "Human" class
each Human has a "name"
the name is set in the constructor (so when you're creating an object) and cannot be changed later ("name" is final; also no "setHuman()")
class Human {
private final String name;
public Human(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Here's a simple Professor class:
by definition, a Professor is a Human (Professor extends Human)
when creating a Professor, you must specify the "name" (which is then passed to the Human constructor)
once you have a Professor, you can call getName() (which is defined on the Human class)
class Professor extends Human {
public Professor(String name) {
super(name);
}
}
Here's a simple Student class:
Student is a little different - in addition to a name, it also has a "semester"
when creating a Student, the constructor requires a name and semester, and the Student class itself keeps track of "semester" – so it's fine to have semester defined on Student, and name defined on Human.
you can call getName() (defined on Human)
you can call getSemester() (defined on Student)
class Student extends Human {
private final int semester;
public Student(String name, int semester) {
super(name);
this.semester = semester;
}
public int getSemester() {
return semester;
}
}
I have the following parent class:
public class Employee {
private String name;
public Employee(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
And 2 child class which extends parent:
public class FullTimeEmployee extends Employee {
private double salary;
public FullTimeEmployee(String name, double salary) {
super(name);
this.salary = salary;
}
public double getSalary() {
return salary*2;
}
}
public class PartTimeEmployee extends Employee {
private double salary;
public PartTimeEmployee(String name, double salary) {
super(name);
this.salary = salary;
}
public double getSalary() {
return salary;
}
}
The scenario:
I am using an ArrayList to contain information about employees. The ArrayList is created at the start of the program, and the type of employee being added into the Arraylist is a child extending parent and only known at runtime through user's input
public class EmployeeApplication {
public static void displayInfo(Employee employee) {
// How do I access the method getSalary() that belong to the specific type determined on runtime?
System.out.println(employee.getSalary()); // <--- ???
}
public static void main(String[] args) {
Scanner keyboardInput = new Scanner(System.in);
System.out.println("Type of employee to add into arraylist: ");
String userInput = keyboardInput.nextLine();
// ArrayList to contain information about employees
ArrayList<Employee> employeeAL = new ArrayList<Employee>();
// Type of employee being created and added into ArrayList is dynamic and only known at run time based on user input
if(userInput.equals("full")) {
employeeAL.add(new FullTimeEmployee("John", 1000));
}
else {
employeeAL.add(new PartTimeEmployee("John", 500));
}
displayInfo(employeeAL.get(0));
keyboardInput.close();
}
}
Now the question:
how do I access the method getSalary() belonging to the specific child type that was determined on runtime? Since the object retrieved from the ArrayList is a parent type. Please note that the salary attribute only belongs to the child class.
My current implementation has me checking for the child type, typecasting it into that child type, and finally accessing the method belonging to the child.
I am trying to avoid typecasting because I believe I am doing things wrongly with regards to good Java coding practise. I'm missing something here but I just don't know what
Another method which I have thought about is to implement the method getSalary() in the parent class and overriding it in the child class, this way, I don't have to typecast but I don't know if this is the right practice since the salary attribute has got no relation with Employee at all:
// Parent
public class Employee {
private String name;
public Employee(String name) {
this.name = name;
}
public String getName() {
return name;
}
// ADDED THIS <----
public double getSalary() {
return 0.0;
}
}
// Child
public class FullTimeEmployee extends Employee {
private double salary;
public FullTimeEmployee(String name, double salary) {
super(name);
this.salary = salary;
}
// ADDED THIS <----
#Override
public double getSalary() {
return salary*2;
}
}
what am I doing wrongly and what is the best Java coding practice?
You can implement Employee as abstract and add getSalary() as an abstract method which forces subclasses of Employee to implement that method
public abstract class Employee {
private String name;
public Employee(String name) {
this.name = name;
}
public String getName() {
return name;
}
abstract protected double getSalary();
}
I have a small assignment on adding and displaying different types of employees(diff. departments) at work and different salary & benefits, using OOP approach. I am quite not sure if my code is correct in terms of code reuse & if did I really meet the OOP coding approach...So far I have displayed 1 employee each type/department, I made them as a class name.(see code below). My question is if I add a new employee I'm going to declare another object of type Employee again. And what if there will be a lot of employees, I will be having a lot of objects. How do I lessen that and may I know if my OOP coding approach is correct so far? Ty very much! Here is my code:
//this is my parent class which implements an interface...
public abstract class Employees implements ICompensation{
private String fname;
private String lname;
private char gender;
private String address;
private double salary;
public String getfname(){
return this.fname;
}
public void setfname(String fname){
this.fname = fname;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
// this is a Developer type of employee
public class Developer extends Employees{
public Developer(String fname,String lname, char gender,String address, double salary){
setfname(fname);
setLname(lname);
setGender(gender);
setAddress(address);
setSalary(salary);
}
#Override
public double calculateSalary() {
double salary = getSalary();
salary += 10;
return salary;
}
#Override
public void print() {
System.out.println(this.getClass());
System.out.println(this.getfname());
System.out.println(this.getLname());
System.out.println(this.getGender());
System.out.println(this.getAddress());
System.out.println(this.calculateSalary());}}
//this is QA type of employee
public class QA extends Employees{
public QA(String fname,String lname,char gender,String address,double salary) {
setfname(fname);
setLname(lname);
setGender(gender);
setAddress(address);
setSalary(salary);
}
#Override
public double calculateSalary() {
double salary = getSalary();
salary = salary + 20;
return salary;
}
#Override
public void print() {
System.out.println(this.getClass());
System.out.println(this.getfname());
System.out.println(this.getLname());
System.out.println(this.getGender());
System.out.println(this.getAddress());
System.out.println(this.calculateSalary());
}
}
I have another 2 classes which are BA & Manager class but I wont include here because it's just have the same contents to the other derived class.
//so here is my Interface
public interface ICompensation {
double calculateSalary();
void print();
}
//and here is my main method.
import java.util.*;
public class main {
public static void main(String[] args){
Employees dev = new Developer("Janel","Logrono",'M',"Alabang",491);
Employees qa = new QA("juan","Sir",'M',"Taguig",1240);
Employees ba = new BA("pedro","Lyn",'F',"Taguig",1150);
Employees manager = new Manager("sebastian","rods",'M',"USA",555399);
ArrayList<Employees> ls = new ArrayList<>();
ls.add(dev);
ls.add(qa);
ls.add(ba);
ls.add(manager);
for(Employees e : ls){
e.print();
System.out.println();
}
}
}
How do add another employee w/o declaring a lot of objects and may I know if my OOP coding approach is correct so far, I think there are a lot of redundant codes here, how to lessen it? thx!
First of all you should not implements ICompensation in the bean class. Bean class will only contain getters, setters & constructor. You need to create another class which will implement the ICompensation. There you will write the code for calculations and other methods.
In database you can add another column "Role" which will define the employee role. By this approach you don't need to create extra methods such as QA, Developer, Manager.
please look into the following link. Here they tried to develop a login page using MVC model. You can just ignore the jsp pages and concentrate on controllers and beans.
https://krazytech.com/programs/a-login-application-in-java-using-model-view-controllermvc-design-pattern
Begging java programming recently, run into an error. please help
Have two classes , PersonTest.java:
public class PersonTest {
public static void main(String[] args) {
Person person1=new Person("dummy","sdymmt","20","male","washington");
System.out.println("Name: "+person1.getName());
System.out.println("Surname: "+person1.getSurname());
System.out.println("Age: "+person1.getAge());
System.out.println("Gender:" +person1.getGender());
System.out.println("Birthplace: "+person1.getBirthplace());
Person person2= new Person(400);
System.out.println("Income:"+person2.getX()+" mije leke");
System.out.println("Tax:"+person2.Taksat()+" mije leke");
Student student1= new Student("adsd","zedsdsadza");
System.out.println("emri"+student1.getEmer());
}
}
and also Person.java :
public class Person {
private String Name;
private String Surname;
private String Age;
private String Gender;
private String Birthplace;
private double x;
public Person()
{
}
public Person(String Name, String Surname, String Age, String Gender, String Birthplace) {
this.Name = Name;
this.Surname = Surname;
this.Age = Age;
this.Gender = Gender;
this.Birthplace = Birthplace;
}
public String getName() {
return Name;
}
public String getSurname() {
return Surname;
}
public String getAge() {
return Age;
}
public String getGender() {
return Gender;
}
public String getBirthplace() {
return Birthplace;
}
public Person(double x) {
this.x = x;
}
public double getX() {
return x;
}
double Taksat() {
return (0.1 * x);
}
public class Student extends Person {
private String University;
private String Faculty;
public Student(String Universiteti, String Fakulteti) {
super(Name, Surname, Age, Gender, Birthplace);
this.Faculty = Fakulteti;
this.University = Universiteti;
}
public String getFaculty() {
return Faculty;
}
public String getUniversity() {
return University;
}
}
}
Two classes are in the same default package. How to fix the fact that the test class doesn't recognize the inner class student as a class.
Nested non static class are called Inner Classes those classes cannot live without the Outer class (which wrapped them).
Java docs
An instance of InnerClass can exist only within an instance of
OuterClass and has direct access to the methods and fields of its
enclosing instance.
To instantiate an inner class, you must first instantiate the outer
class. Then, create the inner object within the outer object with this
syntax:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
Try using:
Person.Student student = person1.new Student(PARAMETERS);
Important Mark:
Of course, you should highly consider that this is not a good design, because you may want this classes to be visible outside of the Person class but also because Person.Student inherits from Person, which it's already contains the Student class, which usually looks like a loop or a circle relationship, which usually not a good idea for the first place.
Because there is no Student class. Since it nested, it's Person.Student
I am trying to access a constructor in an abstract class that is two levels higher.
public abstract class Person{
protected String name;
public Person(String name){
if name.length() <= 12)
this.name = name;
else
this.name = name.substring(0,12);
}
public final String returnName(){
return name;
}
}
public class employee extends person{
public employee(string firstname, string gender){
super(firstname);
this.gender =gender;
}
}
public class dependent extends employee{
public dependent(string firstname, string gender, string relation){
super(firstname);
super(gender);
this.relation = relation;
}
How do I invoke the constructor of the abstract class from the dependent class (two levels below)?
Ok, first of all, here's how you pass two parameters to your Employee constructor:
super(firstname, gender);
Second, there's no need to call the Person constructor from the Dependent one. This will happen automatically when Dependent calls the Employee constructor, because the Employee constructor then calls the Person one.
What you are looking for is something like the below, please note Classes start with Upper-case and camel case for method parameter staring with a lower-case letter. String must be upper-case String name , please also be aware you have introduced a protected member scope on name
See the following post on the implications In Java, difference between default, public, protected, and private
public abstract class Person
{
protected String name;
public Person(String name)
{
if (name.length() <= 12)
{
this.name = name;
}
else
{
this.name = name.substring(0, 12);
}
}
public final String returnName()
{
return name;
}
}
public class Employee extends Person
{
private String gender = null;
public Employee(String firstName, String gender)
{
super(firstName);
this.gender = gender;
}
}
public class Dependent extends Employee
{
private String relation = null;
public Dependent(String firstName, String gender, String relation)
{
super(firstName, gender);
this.relation = relation;
}
}
You will need to add methods to access the relation and gender if you need the access to these
try this:
public class employee extends Person{
public employee(String firstname, String gender){
super(firstname);
this.gender =gender;
}
}
public class dependent extends employee{
public dependent(String firstname, String gender, String relation){
super(firstname,gender);
this.relation = relation;
}