Example from another stackoverflow thread link:
public class RegularEmployee {
private BigDecimal salary;
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
public static BigDecimal getBonusMultiplier() {
return new BigDecimal(".02");
}
public BigDecimal calculateBonus() {
return salary.multiply(getBonusMultiplier());
}
/* ... presumably lots of other code ... */
}
public class SpecialEmployee extends RegularEmployee {
public static BigDecimal getBonusMultiplier() {
return new BigDecimal(".03");
}
}
This doesn't behave as some people might think, because calculateBonus
always takes the getBonusMultiplier
from RegularEmployee
, even if called from an instance of SpecialEmployee
.
public class RegularEmployee {
private BigDecimal salary;
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
public static BigDecimal getBonusMultiplier() {
return new BigDecimal(".02");
}
public BigDecimal calculateBonus() {
try {
return salary.multiply((BigDecimal) this.getClass().getMethod("getBonusMultiplier").invoke(null));
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
Logger.getLogger(Parent.class.getName()).log(Level.SEVERE, null, ex);
}
}
/* ... presumably lots of other code ... */
}
public class SpecialEmployee extends RegularEmployee {
public static BigDecimal getBonusMultiplier() {
return new BigDecimal(".03");
}
}
This does call the getBonusMultiplier()
from SpecialEmployee
if called from a SpecialEmployee
instance.
My question is: why doesn't Java provide implicit use of Method class' invoke like this? The code would be much more readable if I could achieve the same with:
public class RegularEmployee {
private BigDecimal salary;
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
public static BigDecimal getBonusMultiplier() {
return new BigDecimal(".02");
}
public BigDecimal calculateBonus() {
return salary.multiply(origin.getBonusMultiplier());
}
/* ... presumably lots of other code ... */
}
public class SpecialEmployee extends RegularEmployee {
public static BigDecimal getBonusMultiplier() {
return new BigDecimal(".03");
}
}
EDIT: So it seems like people consider my design bad. Therefore I'll try to improve on it:
public class RegularEmployee {
private BigDecimal salary;
protected bonusMultiplier;
public RegularEmployee(){
bonusMultiplier = getBonusMultiplier();
}
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
public static BigDecimal getBonusMultiplier() {
return new BigDecimal(".02");
}
public BigDecimal calculateBonus() {
return salary.multiply(bonusMultiplier);
}
/* ... presumably lots of other code ... */
}
public class SpecialEmployee extends RegularEmployee {
public SpecialEmployee(){
bonusMultiplier = getBonusMultiplier();
}
public static BigDecimal getBonusMultiplier() {
return new BigDecimal(".03");
}
}
It works, it doesn't misuse Reflection and gives customizability to the getBonusMultiplier, just like the original example. There is only one thing I don't like about this piece of code: having to copy code from the constructor of RegularEmployee to the constructor of SpecialEmployee. I know that they are semantically different due to hiding the parent method, but still, I prefer not having to copy code. Can anyone give me a solution without having to copy code? (Or in other words: can anyone give me a lazy programmers solution? :P)