Can fields that have been inherited 2 levels deep be changed directly? - java

I am doing an edx Java course, and one of the module tasks is to write a program that makes an Employee class, that is then extended by a TechnicalEmployee, and that is extended by TechnicalLead. I construct a TechnicalLead that then gets all the fields and methods of its' parents. However, I am asked to change the salary specifically for the TechnicalLead to be 1.3 times that of what I set in TechnicalEmployee. Since we are given specific methods which we need to work with, I can't find a way to change the salary directly from TechnicalLead without adding my own custom setSalary method in the Employee class. I have also set all the fields as private.
public abstract class Employee {
private String name="";
private double salary=0;
private static int cnt=0;
private int id=0;
public Employee(String name, double baseSalary){
this.name=name;
this.salary=baseSalary;
this.id = ++cnt;
}
public abstract class TechnicalEmployee extends Employee {
private int checkins=0;
public TechnicalEmployee(String name){
super(name,75000);
}
public class TechnicalLead extends TechnicalEmployee {
boolean Manager=true;
public TechnicalLead(String name){
super(name);
}
There are 2 classes under TechnicalEmployee, TechnicalLead that gets a raise to 1.3 the baseSalary, and SoftwareEngineer which remains at its' initial baseSalary. Is there a way for me to change the salary field from TechnicalLead without adding an additional setSalary method in the Employee class and without changing the field to public?

*The table is for understanding the usage of access modifiers.
If you have your variable access modifier set as public or protected you can access the variable from child classes within the same package. If the package is different again you can not use protected to get there.
To access it from anywhere use public but do it only if necessary cause that opens the possibility of viewing and editing all values of the class from anywhere. and hence destroys the concept of hiding important data.
You can also go through the article PuProDePri in linkedIn(https://www.linkedin.com/pulse/puprodepri-ajitav-basak/) for some quick tips to remember the access modifier rule.

Related

Accessing a childs instance variables in superclass?

I have a method that writes data into a file in my superclass(Employee). I need to write data of other employees in that method, but I am unsure how to access the instance variables in my child classes in order to accomplish this.
public class Employee
{
protected String name;
protected String employeeNum;
protected String department;
protected char type;
}
public void writeData()
{
BufferedWriter printer = new BufferedWriter(new FileWriter("fileName"));
//code here that adds Employee information, and Commission information to file
}
public class Commission extends Employee
{
private int weeksStart;
private double baseWeeklySalary;
private double salesWeekly;
private double totalSales;
private double commissionRate;
}
Commission information is not accessible in superclass however you can override the writeData() in subclass which give you access to both Employee and Commission information.
#override
public void writeData()
{
BufferedWriter printer = new BufferedWriter(new FileWriter("fileName"));
String data="name:"+name+","+"employeeNum:"+employeeNum+
","+"......"+","+"weeksStart:"+weeksStart;
printer.write(data);
}
I'm having a little trouble understanding your question, but if I'm correct you're wondering how to access the private members of Commission externally from an instance of Employee. If that's correct, here:
The problem here lies in your use of Polymorphism without properly structuring the Commission child class to allow access to the private members you want. Since the members are private, you cannot access them from any other class. You need to add get/set methods to the Commission class to access these private members. This lets them be accessed in strict manners while still being protected from external adjustment.
For instance, if you wanted to set or get the commissionRate, you could add methods into the commission class such as:
public void setCommissionRate(double newRate){
//Confirming a non-negative input - set checks appropriately for your use
if(newRate >= 0)
commissionRate = newRate;
}
public double getCommissionRate(){
return commissionRate;
}
This will give access to other classes to the private members of your choosing. However, set methods are usually more scarce than get methods for private members since it can give too much access to external classes, and usually are either inherited or added in a constructor.
If accessing from an Employee instance, an overridden write method is necessary in the commission class to allow access to its members.
Hopefully I answered your primary question and this helps you out.

How to inherit fields properly without making them open to the package?

Say, I have a package Pack containing classes A and B. A is self-contained and no one (even in the Pack) should see A's insides, so most of the fields and methods are private.
Now I want to extend A to change one of its private methods keeping the rest - let it be class AMod. Doing it requires most of A's fields and the method to override to be protected, but protected gives access to the package.
So how do I create AMod inside Pack so that AMod has an access to A's fields and methods while no one else does? Make a nested/separate package?
UPD:
UPD2:
UPD3:
As Jacob G. suggested, my code needed redesigning, and I managed to remove the derived class from the architecture. Thanks for help!
The one answer I find missing: don't be so focused on using inheritance in order to avoid code duplication.
If you only need a subtle variation of behavior of A then you should first consider to "wrap" around A (for example via decorator) instead of extending A - the good old FCoI!
If that isn't possible: have a very close look at the common behavior of A and Amod and extract those parts in a common base class.
Finally: don't get too energetic about java access modifiers in the first place. In the end, they help you to communicate a certain thought or idea. "Evil-willing" people will always find a way to work around your intentions. What I am saying is: if you are concerned that your team members use your class in the wrong way ... that is a social problem; and you will never be able to solve that on the technical layer. You have to solve it on the social layer, too (by educating people to ensure that they understand what to do; instead of hoping that private here or protected there will prevent them from doing the wrong thing).
In other words: establish a simple policy such as "only what is marked public is meant to be public; anything else is not" might be able to table such discussions for all times. Versus spending hours and hours to find a perfect private-protected solution within source code.
Thanks for posting code.
My advice would be to first move B#stepBMod into A.java. Then, you can pass a boolean parameter to A#build; with this, you can rewrite A#build:
public Result build(boolean mod) {
stepA();
if (mod) {
stepBMod();
} else {
stepB();
}
stepC();
return result;
}
Now, B.java isn't needed anymore.
Your question is two parts. 1)Accessing fields and 2)Accessing methods.
Case1), you should make class A's fields protected. This means no one can access it by name, except derived classes.
Case2), you cannot access a protected method by name, unless in a derived class. But still you can access a protected method by name using an object of A. In order to prevent other classes making objects, your A class should be abstract.
Here is an example
public abstract class A{
protected int n;
protected void display(){
System.out.println(n);
}
}
public class B extends A{
public void demo(){
B object = new B();
object.display();
}
public void modify(){
n = 0;
}
}
Update
class A
{
public A(Args args){...}
public Result build() {
stepA();
stepB();
stepC();
return result;
}
protected void stepA() {...}
private void stepB() {...}
protected void stepC() {...}
protected T field;
}
class AMod extends A
{
public AMod(Args args){
super(args);
...
}
public Result build() {
stepA();
stepBMod();
stepC();
return result;
}
private void stepBMod() {...}
}

In Java is it correct to allow subclass to alter superclass private fields via public setter method?

Please look at the code below
Class Employee{
private String name;
private String id;
public String getName(){ return name; }
public void setName(String name){ this.name = name; }
public String getId(){ return id; }
public void setId(String id){ this.id = id; }
}
Class Teacher extends Employee{
private double salary;
}
Now my question is If I am creating an object of Teacher , then it does not make sense without the Teacher object having a name and id. I can set the same for teacher object via public setters of Employee but it it correct ?
Teacher t1 = new Teacher();
t1.setName("aaa");
t1.setId("224");
t1.salary = 200.00;
System.out.println(t1.toString());
I am asking this question as my understanding is if the field is private it should be used only via getters . But in the example provided above Teacher object will not make sense without having a Name or Id .
If it is correct then why not make the field public in the first place? What is the advantage in using it private and then allowing access via public setter ?
If it is not correct please provide an example of how the above Employee and Teacher class should be implemented ?
Your question seem to show a confusion between two concepts rather independant:
encapsulation
creation of objects
Encapsulation: it is better design to define private variables. Then you can not corrupt the object from outside. You must use setter to modify your employee.
But, if you trust Teacher, it could modify Employee as a subclass, without setter, it is faster to code (but little risky: if you have to change the setter in employee, Teacher wont get it, ...).
Creation of objects: you should pass certain values to the variables, or they are defined by default (or auto-built ...)
=> you can decide that Teacher have well defined values (default), or that you must give these values (mandatory). It is your design.
After that, you can change them directly or by setters of Employee (=> first concept of encapsulation).
then it does not make sense without the Teacher object having a name and id. I can set the same for teacher object via public setters of Employee but it it correct ?
This is where exactly constructor comes into picture. You need to pass them before you are using it.
Thumbrule : When you want something while building it, you need to force them to pass on constructor.

Different methods need different attributes in one object

I have a given web service. (This is only an example, the real one is more complex, but it has the same problem.) The service has three methods and all three methods have a person as parameter and need other things from it. (I can't change the entity or methods.)
Entity (Person) (It has only a default constructor):
private String name;
private int age;
private Address address;
private List<String> hobbies;
private List<Person> friends;
Method1 needs name and age.
Method2 needs address name and age.
Method3 needs all.
I need to fill the object from my own objects. I need to write a "converter". What is the best practice for it?
My solutions:
Builder Pattern with builds for three methods.
Set all attributes and send unhandled overhead (bad solution in my eyes).
Creating a builder that sets only required fields sounds good.
You can inherit from this class for each of your needs and implement your own constructors
public class Target {
// fields
}
public class Purpose1 extends Target {
public Purpose1(String name, int age) {
// set fields or do whatever you wish
}
}
public class Purpose2 extends Target {
public Purpose2(String address, String name, int age) {
// set fields or do whatever you wish
}
}
public class Purpose3 extends Target {
public Purpose3(...) {
// set fields or do whatever you wish
}
}
And then you may use instances of subclasses where class Target is required.
I think you can get what you want with a suitable usage of decorator pattern:
https://en.wikipedia.org/wiki/Decorator_pattern

Call a child class method from a parent class object

I have the following classes
class Person {
private String name;
void getName(){...}}
class Student extends Person{
String class;
void getClass(){...}
}
class Teacher extends Person{
String experience;
void getExperience(){...}
}
This is just a simplified version of my actual schema. Initially I don't know the type of person that needs to be created, so the function that handles the creation of these objects takes the general Person object as a parameter.
void calculate(Person p){...}
Now I want to access the methods of the child classes using this parent class object. I also need to access parent class methods from time to time so I CANNOT MAKE IT ABSTRACT.
I guess I simplified too much in the above example, so here goes , this is the actual structure.
class Question {
// private attributes
:
private QuestionOption option;
// getters and setters for private attributes
:
public QuestionOption getOption(){...}
}
class QuestionOption{
....
}
class ChoiceQuestionOption extends QuestionOption{
private boolean allowMultiple;
public boolean getMultiple(){...}
}
class Survey{
void renderSurvey(Question q) {
/*
Depending on the type of question (choice, dropdwn or other, I have to render
the question on the UI. The class that calls this doesnt have compile time
knowledge of the type of question that is going to be rendered. Each question
type has its own rendering function. If this is for choice , I need to access
its functions using q.
*/
if(q.getOption().getMultiple())
{...}
}
}
The if statement says "cannot find getMultiple for QuestionOption." OuestionOption has many more child classes that have different types of methods that are not common among the children (getMultiple is not common among the children)
NOTE: Though this is possible, it is not at all recommended as it kind of destroys the reason for inheritance. The best way would be to restructure your application design so that there are NO parent to child dependencies. A parent should not ever need to know its children or their capabilities.
However.. you should be able to do it like:
void calculate(Person p) {
((Student)p).method();
}
a safe way would be:
void calculate(Person p) {
if(p instanceof Student) ((Student)p).method();
}
A parent class should not have knowledge of child classes. You can implement a method calculate() and override it in every subclass:
class Person {
String name;
void getName(){...}
void calculate();
}
and then
class Student extends Person{
String class;
void getClass(){...}
#Override
void calculate() {
// do something with a Student
}
}
and
class Teacher extends Person{
String experience;
void getExperience(){...}
#Override
void calculate() {
// do something with a Teacher
}
}
By the way. Your statement about abstract classes is confusing. You can call methods defined in an abstract class, but of course only of instances of subclasses.
In your example you can make Person abstract and the use getName() on instanced of Student and Teacher.
Many of the answers here are suggesting implementing variant types using "Classical Object-Oriented Decomposition". That is, anything which might be needed on one of the variants has to be declared at the base of the hierarchy. I submit that this is a type-safe, but often very bad, approach. You either end up exposing all internal properties of all the different variants (most of which are "invalid" for each particular variant) or you end up cluttering the API of the hierarchy with tons of procedural methods (which means you have to recompile every time a new procedure is dreamed up).
I hesitate to do this, but here is a shameless plug for a blog post I wrote that outlines about 8 ways to do variant types in Java. They all suck, because Java sucks at variant types. So far the only JVM language that gets it right is Scala.
http://jazzjuice.blogspot.com/2010/10/6-things-i-hate-about-java-or-scala-is.html
The Scala creators actually wrote a paper about three of the eight ways. If I can track it down, I'll update this answer with a link.
UPDATE: found it here.
Why don't you just write an empty method in Person and override it in the children classes? And call it, when it needs to be:
void caluculate(Person p){
p.dotheCalculate();
}
This would mean you have to have the same method in both children classes, but i don't see why this would be a problem at all.
I had the same situation and I found a way around with a bit of engineering as follows - -
You have to have your method in parent class without any parameter and use - -
Class<? extends Person> cl = this.getClass(); // inside parent class
Now, with 'cl' you can access all child class fields with their name and initialized values by using - -
cl.getDeclaredFields(); cl.getField("myfield"); // and many more
In this situation your 'this' pointer will reference your child class object if you are calling parent method through your child class object.
Another thing you might need to use is Object obj = cl.newInstance();
Let me know if still you got stucked somewhere.
class Car extends Vehicle {
protected int numberOfSeats = 1;
public int getNumberOfSeats() {
return this.numberOfSeats;
}
public void printNumberOfSeats() {
// return this.numberOfSeats;
System.out.println(numberOfSeats);
}
}
//Parent class
class Vehicle {
protected String licensePlate = null;
public void setLicensePlate(String license) {
this.licensePlate = license;
System.out.println(licensePlate);
}
public static void main(String []args) {
Vehicle c = new Vehicle();
c.setLicensePlate("LASKF12341");
//Used downcasting to call the child method from the parent class.
//Downcasting = It’s the casting from a superclass to a subclass.
Vehicle d = new Car();
((Car) d).printNumberOfSeats();
}
}
One possible solution can be
class Survey{
void renderSurvey(Question q) {
/*
Depending on the type of question (choice, dropdwn or other, I have to render
the question on the UI. The class that calls this doesnt have compile time
knowledge of the type of question that is going to be rendered. Each question
type has its own rendering function. If this is for choice , I need to access
its functions using q.
*/
if(q.getOption() instanceof ChoiceQuestionOption)
{
ChoiceQuestionOption choiceQuestion = (ChoiceQuestionOption)q.getOption();
boolean result = choiceQuestion.getMultiple();
//do something with result......
}
}
}

Categories

Resources