Override Setter in Subclass - java

I'm stuck with a problem here. I want to change the setter from a attribute from the superclass (parent class) in my subclass (child) however when I overide this method in my subclass I can't access my private attributes from the supperclass. And the point is, they have to stay private.
Superclass (problem: setMinimumVoorraad(int voorraad);)
package domein;
public abstract class Artikel implements Weegbaar
{
private String omschrijving;
private double prijs;
private int aantalInStock;
private int minimumVoorraad;
public Artikel(String omschrijving, double prijs, int aantalInStock, int minimumVoorraad)
{
this.setOmschrijving(omschrijving);
this.setPrijs(prijs);
this.setAantalInStock(aantalInStock);
this.setMinimumVoorraad(minimumVoorraad);
}
#Override
public String toString()
{
String output = String.format(" \n omschrijving: %s \n prijs: %f \n In stock %d (minimumvoorraad = %d) \n", this.omschrijving, this.prijs, this.aantalInStock, this.minimumVoorraad);
return output;
}
//----Getters----
public String getOmschrijving() {
return omschrijving;
}
public double getPrijs() {
return prijs;
}
public int getAantalInStock() {
return aantalInStock;
}
public int getMinimumVoorraad() {
return minimumVoorraad;
}
//----Setters----
public void setOmschrijving(String omschrijving) {
this.omschrijving = omschrijving;
}
public void setPrijs(double prijs) {
this.prijs = prijs;
}
public void setAantalInStock(int aantalInStock) {
this.aantalInStock = aantalInStock;
}
public void setMinimumVoorraad(int minimumVoorraad)
{
if(minimumVoorraad < 2)
this.minimumVoorraad = 3;
else
this.minimumVoorraad = minimumVoorraad;
}
}
Subclass
package domein;
public class Food extends Artikel
{
private String houdbaarheidsDatum;
private double nettoGewicht;
public Food(String omschrijving, double prijs, int aantalInStock, int minimumVoorraad, String houdbaarheidsDatum, double nettoGewicht)
{
super(omschrijving, prijs, aantalInStock, minimumVoorraad);
this.setHoudbaarheidsDatum(houdbaarheidsDatum);
this.setNettoGewicht(nettoGewicht);
}
#Override
public boolean isWeegbaar()
{
return true;
}
//----Getters----
public String getHoudbaarheidsDatum() {
return houdbaarheidsDatum;
}
public double getNettoGewicht() {
return nettoGewicht;
}
//----Setters----
public void setHoudbaarheidsDatum(String houdbaarheidsDatum) {
this.houdbaarheidsDatum = houdbaarheidsDatum;
}
public void setNettoGewicht(double nettoGewicht) {
this.nettoGewicht = nettoGewicht;
}
#Override
public void setMinimumVoorraad(int minimumVoorraad)
{
if(minimumVoorraad < 5)
this.minimumVoorraad = 6;
else
this.minimumVoorraad = minimumVoorraad;
}
}
Someone who can help me?
Thanks in advance.

One possibility is to implement the subclass's setter in terms of the superclass's setter (which, presumably, you do have access to).
For example, assuming the setter is setFoo, then the subclass's version might be:
public void setFoo(Foo f) {
// Do subclass stuff pre-setting, if any
super.setFoo(f);
// Do subclass stuff post-setting, if any
}

The answer given above by NPE is absolutely the best way to go about solving this problem. It is elegant and honors basic inheritance contracts between superclass and subclass. Even in your original post, the subclass is actually more restrictive than the superclass, so doing something like:
#Override
public void setMinimumVoorraad(int minimumVoorraad)
{
if(minimumVoorraad <= 5)
super.setMinimumVoorraad(6);
else
super.setMinimumVoorraad(minimumVoorraad);
}
exactly as NPE suggested would probably work. (Note how I modified your if test. Not sure if it's a typo, but in the original implementation 5 would be a valid minimum, but input like 4 would set it to 6.)
Other (possibly acceptable) patterns would be to:
Make the members in your Parent class protected, which would give visibility. (Realize that you did mention a private restriction; this pattern is solely mentioned to provide a more complete overall answer.)
Delegate the validation logic to another method (that is non-private). This way the child can override the validation method.
And now on to the (probably unacceptable) pattern of using Java reflection:
#Override
public void setMinimumVoorraad(int minimumVoorraad) {
try {
Field field = this.getClass().getSuperclass().getDeclaredField("minimumVoorraad");
field.setAccessible(true);
if(minimumVoorraad <= 5)
field.set(this, 6);
else
field.set(this, minimumVoorraad);
field.setAccessible(false);
}
catch(NoSuchFieldException | IllegalAccessException e) {
// do something
}
}
It's worth noting that if you never ever do this in your entire life you will probably be the better for it. Not only does it completely break all contracts, but it relies on hard-coded Strings to do field name lookups, which in and of itself is pretty painful. But it does exist. And no good answer (already given above by NPE) would be complete without an example of how not to do something...

Related

Setting a boolean value in Constructor, changing it in a method, return it in another

I'm a newbie yet, so please feel free to accuse me of asking silly things xD. I just started coding. So I want to specify my question to make it clear for you. I'm stuck regarding this: We need a constructor (public DoggoII) which sets our value to false. Then we need a method (makeGoodBoi()) to set the value to true and then I need another method (isGoodBoi()) to return the value of the private field goodBoi and System.out.print some stuff later. Consider the rest of the code as done. Can someone give me a hint or something on how to do that? Because I'm kinda lost.
The question is if I have a fault that I can't find and how to return a boolean value in another method in general. Thanks!
public class Doggo {
private String name;
private boolean goodBoi;
public Doggo(String name){
this.name = name;
}
public String getName() {
return name;
}
public void makeBark() {
System.out.println(name + " said: Woof woof");
}
public Doggo (boolean goodBoi){
this.goodBoi= false;
}
public void makeGoodBoi(){
this.goodBoi = !this.goodBoi;
}
public void isGoodBoi(){
if (makeGoodBoi()){
return;
}
}
public void whosAGoodBoi() {
if (isGoodBoi()) {
System.out.println(name + " is such a good boii");
} else {
System.out.println(name + " is not a good boi :(");
}
}
public static void main(String[] args) {
Doggo dog = new Doggo("Casper");
System.out.println(dog.getName());
dog.makeBark();
}
}
Just a basic getter, use boolean as return type instead of void.
public boolean isGoodBoi() {
return goodBoi;
}
Since goodBoi is a class member and by default boolean class members are false, so you don’t have to do anything except add a getter
public boolean isGoodBoi() {
return goodBoi;
}
This will send whatever current value of class member is.
So getting this would be as simple as;
DOGGO_OBJECT.isGoodBoi();
Then we need a method (makeGoodBoi()) to set the value to true and then I need another method (isGoodBoi()) to return the value of the private field goodBoi and System.out.print some stuff later.
public void makeGoodBoi() {
this.goodBoi = true;
}

Constructors and methods in java

I want to create the below class
associatename:String
workstatus:String
associate() :constructor
getassociatename():String
setassociatename(String):void
getworkstatus()String
tracksassociatestatus():int
setworkstatus(String):void
The trackAssociateStatus method takes the number of days as argument and sets the work status of the associate based on the number of days. The first 20 days they learn “C”, the next 20 days they learn “Java” In the Main class invoke the trackAssociateStatus method and find the work status and display the output.
output:The associate abc work status:Project phase
I tried this....But i got error
//associate class
public class associate{
private int associatename;
private String workstatus;
private int days;
void associate()
{
getassociatename();
setassociatename();
getworkstatus();
tracksassociatestatus();
setworkstatus();
}
public int getassociatename()
{
return associatename;
}
public void setassociatename(int associatename)
{
this.associatename=associatename;
}
public String getworkstatus()
{
return workstatus;
}
public void tracksassociatestatus(int days)
{
if(days<20)
setworkstatus("C");
else
setworkstatus("Java");
}
public void setworkstatus(String workstatus)
{
this.workstatus=workstatus;
}
}
//main class
associate a =new associate();
Scanner in=new Scanner(System.in);
int associateid=0;
String workstatus=null;
int days=0;
System.out.println("Enter the associateid:");
associateid=in.nextInt();
a.associateid=(associateid);
System.out.println("Enter the no of days:");
days=in.nextInt();
a.trackassociatestatus();
System.out.println("The id is "+a.getassocaiteid()+" work status "+a.getworkstatus());
Based on your (seemingly) UML spec, your class would look like the following:
public class Associate {
private String associateName;
private String workStatus;
public Associate() {
// This constructor is optional, a no-args constructor is added by the compiler to any class not explicitly naming a constructor.
}
public String getAssociateName() {
return associateName;
}
public void setAssociateName(String associateName) {
this.associateName = associateName;
}
public String getWorkStatus() {
return workStatus;
}
public void setWorkStatus(String workStatus) {
this.workStatus = workStatus;
}
public int tracksAssociateStatus() {
// TODO write logic here
return 1; // TODO change to whatever you need to return
}
}
You were specifying int for getAssociateName, when associateName is a String. This won't work; you need your getter return type to be the same as your field data type, or you need to convert the data to the method's return type. (The former is best practice).
Constructors don't specify a type, the class name is used and the compiler will understand what you want to do (which is return a new instance of the class). Therefore, your void associate() will tell the compiler "create a method called associate that doesn't return anything".
Well, would be nice if you provide the error itself for us.
But meanwhile, have you notice that your tracksassociatestatus method recieves an integer parameter days, and your constructor passes nothing to it?
So try changing your constructor to be something like:
Public associate() {
getassociatename();
setassociatename();
getworkstatus();
tracksassociatestatus(10);
setworkstatus();
}
For a cleaner code, check the other answer.
If you still have errors, please share them.
import java.util.*;
public class Associate
{
private String associateName;
private int workStatus;
private int days;
Scanner sc = new Scanner(System.in);
public String getAssociateName()
{
System.out.println("Enter the Associate id:");
associateName = sc.nextLine();
return associateName;
}
public void setassociatename(int associatename)
{
this.associateName=associateName;
}
public String tracksAssociatename()
{
return associateName;
}
public int getWorkStatus()
{
System.out.println("Enter the number of days");
days = sc.nextInt();
return days;
}
public void setWorkStatus(String workStatus)
{
this.workStatus=workStatus;
}
enter code here
public `enter code here`int tracksAssociateStatus()
{
return days;
}
public static void main(String args[])
{
Associate obj = new Associate();
obj.getAssociateName();
obj.getworkstatus();
System.out.println("The Associate name "+obj.tracksAssociatename()+" work Status "+obj.tracksAssociateStatus());
}
}

Check if class has a variable in its constructor based on a string?

Let's say I have a class named Person and its constructor had variables like name, age, hairColor and so on. If I had a function that receives a string that should match one of the class's variables, how could I check if that class actually had that variable and how could I go about modifying it? For example:
public class Person {
public String name;
public int age;
public String hairColor;
public Person() {
name = "Bryce";
age = 21;
hairColor = "brown";
}
public void changeHairColor(String variable, String color) {
if (/*this class contains the variable passed as an argument to this method*/) {
// Person[variable] = color
}
}
}
I'm a python dev, mostly, so the method changeHairColor has some pseudo-python in it. I want to be able to edit the variable in a similar way you could edit variables inside of dictionaries with Python:
person = {
"name": "Bryce",
"age": 21,
"hairColor": "brown"
}
def changeHairColor(variable, color):
person[variable] = color
If that is at all possible.
The only way to do it in Java is to use Java Reflection API:
public class Test {
public String name;
public int age;
public String hairColor;
public void setProperty(String property, Object value) {
try {
Field declaredField = this.getClass().getDeclaredField(property);
switch (declaredField.getAnnotatedType().getType().getTypeName()) {
case "java.lang.String":
declaredField.set(this, value);
break;
// handle other types
}
} catch (NoSuchFieldException e) {
// handle exception
} catch (IllegalAccessException e) {
// handle exception
}
}
public static void main(String[] args) {
Test test = new Test();
test.setProperty("name", "Bob");
System.out.println(test.name);
}
}
I would not solve this with reflection. If your PlayerCharacter has an enumerable set of attributes, I would model these as a Java enum and store the attribute values within the PlayerCharacter object in an EnumMap:
import java.util.EnumMap;
public class PlayerCharacter {
public enum Attribute {
AGILITY,
DEXTERITY,
/* etc ...*/
VITALITY
}
private EnumMap<Attribute, Integer> attributes = new EnumMap<>(Attribute.class);
public PlayerCharacter() {
// initialize each attribute with a default value (0 in this example)
for (Attribute a : Attribute.values()) {
attributes.put(a, new Integer(0));
}
}
public int getValue(Attribute attribute) {
return attributes.get(attribute);
}
public void levelUp(Attribute attribute, int amount) {
attributes.put(attribute, attributes.get(attribute) + amount);
}
}
The biggest benefit of using an enum instead of plain old String (+reflection), is that this way you get compile-time type safety for the code that's using your PlayerCharacter.
Using Reflection API, you can access the methods and properties on an object at run time. The other answer describes its usage. But I don't recommend reflections for your problem. How about the following:
public void changeHairColor(String variable, String color) {
if("name".equalsIgnoreCase(variable))
this.name = color;
else if("age".equalsIgnoreCase(variable))
this.age = Integer.parseInt(color);
else if("color".equalsIgnoreCase(variable))
this.color = color;
else
throw new Exception ("error - property not available");
}
}
Note, your existing method name 'changeHairColor' doesn't make sense in the context. It should be someething like 'changeProperty' because you are not just changing the 'color', you are changing any available property with this method.

Using the Check class, add the code to have the Checks sorted by checkNumber

Using the Check class, add the code to have the Checks sorted by checkNumber.
import java.util.Date;
public class Check implements Comparable {
private int checkNumber;
private String payTo;
private Date date;
private float amount;
public int compareTo(Object arg0) {
//Insert code here
}
public int getCheckNumber() {
return checkNumber;
}
public void setCheckNumber(int checkNumber) {
this.checkNumber = checkNumber;
}
public String getPayTo() {
return payTo;
}
public void setPayTo (String payTo) {
this.payTo = payTo;
}
public Date getDate() {
return date;
}
public void setDate (Date date) {
this.date = date;
}
public float getAmount() {
return amount;
}
public void setAmount (float amount) {
this.amount = amount;
}
}
My solution is below, but it does not seem to work.
Can anyone help me with the solution?
public int compareTo(Object arg0) {
if(this.checkNumber == arg0.checkNumber)
return 0;
else
return this.checkNumber > arg0.checkNumber ? 1 : -1;
}
You didn't specify what you mean by "doesn't work", but reading your code, I'm assuming you get a compilation error.
The reason for this is because the code you were given has not specified a type for the comparable, so it doesn't know what type you even want to compare it to. It will use Object by default, which does not (by design) know a thing about Check's fields and methods.
The following modification is the best solution:
public class Check implements Comparable<Check> {
public int compareTo(Check arg0) {/* ...*/ }
}
This will force you to compare this to other Check's only and make arg0 a Check object, rendering its fields and methods available to you.
Should the parameters of the problem you were given not allow you to modify the provided code, then the (very very distant) second best solution is:
public int compareTo(Object arg0) {
Check other = null;
if(arg0 instanceof Check)
other = (Check)arg0;
// Other checks.
}
This adaptation would technically work for your problem given the stipulation that you are not allowed to modify the provided code, but is otherwise not at all recommended, as the contract for Comparable wants the type of object you wish to compare against to be specified, and not specifying it can introduce problems.
In fact, I'd say you are fully allowed to tell the person who gave you this problem that they are a terrible person for giving you a problem with this mistake in it, because not specifying a Comparable type is a really bad practice. Especially if they're teaching you how to program.

Implementation question regarding base classes and derived classes

I have a question regarding the best way to implement this. I'm going to describe my current implementation and how I seem to have painted myself into a corner:
I have an abstract class called Package:
public abstract class Package {
protected String description;
protected String packagingCode;
protected Dimension dimensions;
protected Weight weight;
protected Package() {
this.description = null;
this.packagingCode = null;
this.dimensions = null;
this.weight = null;
}
protected Package(String description, String packagingCode, Dimension dimensions, Weight weight) throws ShippingException {
this.description = description;
this.packagingCode = packagingCode;
this.dimensions = dimensions;
this.weight = weight;
String exceptionMessage = "";
if(!meetsWeightRequirements()) {
exceptionMessage = "This package's weight exceeds limits. ";
}
if(!meetsDimensionalRequirements()) {
exceptionMessage += "This package's dimensions exceed limits.";
}
if(!StringUtils.isEmpty(exceptionMessage)) {
throw new ShippingException(exceptionMessage);
}
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPackagingCode() {
return packagingCode;
}
public void setPackagingCode(String packagingCode) {
this.packagingCode = packagingCode;
}
public Dimension getPackageDimensions() {
return dimensions;
}
public void setPackageDimensions(Dimension dimensions) throws ShippingException {
this.dimensions = dimensions;
if(!meetsDimensionalRequirements()) {
this.dimensions = null;
throw new ShippingException("This package's dimensions exceed limits.");
}
}
public Weight getPackageWeight() {
return weight;
}
public void setPackageWeight(Weight weight) throws ShippingException {
this.weight = weight;
if(!meetsWeightRequirements()) {
this.weight = null;
throw new ShippingException("This package's weight exceeds limits.");
}
}
public abstract boolean meetsWeightRequirements();
public abstract boolean meetsDimensionalRequirements();
}
Then I have classes that extend this abstract class like so:
public class WeightBasedPackage extends Package {
public boolean meetsWeightRequirements() {
Weight weight = this.getPackageWeight();
boolean meetsRequirements = false;
if(weight != null) {
meetsRequirements = (weight.getWeight() > 0);
}
return meetsRequirements;
}
public boolean meetsDimensionalRequirements() {
return true;
}
}
I have another object (ShipRequest) that maintains a List of Packages (List<Package>). I also have a services (eg WeightBasedPackageShipService) that uses this object and can access this list of packages. This implementation has worked fine because the services don't really care what type of package it is. The only difference between the packages is the way they implement the abstract methods.
Now here is where the problem comes in. I created a new class:
public class OrderQuantityPackage extends Package {
int quantity;
public OrderQuantityPackage() {
super();
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public int getQuantity() {
return this.quantity;
}
public boolean meetsWeightRequirements() {
return true;
}
public boolean meetsDimensionalRequirements() {
return true;
}
}
Which has a quantity field. I need to access this field in the service (OrderQuantityPackageShipService). However, since it is of type Package I have to cast it (it seems kinda kludgey).
My question is, how do I implement this in a better fashion (so I don't have to cast) and also ensure type-safety (So that if you are using OrderQuantityPackageShipService, the package must be of type OrderQuantityPackage). I thought about using Generics, but it seems a little to kludgey for what I am trying to do (ShipRequest has a bunch of other attributes and it seemed strange to genericize it based on the type of package).
Thanks.
public abstract class Package {
protected String description; // These shouldn't be private fields instead of protected?
protected String packagingCode; // Nah, I don't think so, otherwise how could I store a value into the Quantity field? =P
protected Dimension dimensions;
protected Weight weight;
protected int quantity;
// Constructors, getters and setters...
public virtual int getQuantity {
throw new NotImplementedException();
}
public virtual int setQuantity(int quantity) {
throw new NotImplementedException();
}
}
public final class OrderQuantityPackage extends Package {
public override int getQuantity {
return super.quantity;
}
public override void setQuantity(int quantity) {
super.quantity = quantity;
}
}
I'm not completely sure about the syntax though, and neither about the NotImplementedException, but I hope you get the idea. So, any Package derived class that needs or require a quantity may do so by overriding the getter and setter of the Quantity property.
No exception should be thrown as of where the Quantity won't be required, it shouldn't get called, so no exception shall be thrown. Furthermore, it testifies that your model only does what it is required when times come.
In addition to it, OrderQuantityShipService shouldn't require a Weight property within the OrderQuantityPackage, and as written by Vivin, one could access the weight anyway.
Otherwise, a simple cast within your service should do it. It is no dirty way to go to use casting. For instance, one must cast the sender object within an event handler to the proper control type he wishes to check for name, state or other property values! The most general class is then passed on to the event, and one must cast... And this, that is not me who said to opt this way, these are software engineers!...
EDIT Vivin, how do one cast from a data type to another in JAVA, is it as in C/C++/C# ?
CastedType variable = (CastedType)TypeCast;
Short Answer: Dependency Inversion
You have a OrderQuantityPackageShipService class that requires certain features from the objects that it processes. So OrderQuantityPackageShipService should be the one specifying those requirements. Typically this is done with an interface. If it is very specific to the service, create the interface nested. ie:
class OrderQuantityPackageShipService {
//...
interface QuantityPackage {
int getQuantity();
// ...
}
}
if it can be used in a consistent manner by other services, define it outside of the OrderQuantityPackageShipService class.
Then have certain packages implement that interface...
Maybe you should create an abstract service and extend it for the different kinds of packages to handle. You could have the handling method be abstract and have each kind of service know what to do with the corresponding package. If you're not to mix types of packages then this might work.
One thing I can think of is why would you need to access the quantity attribute in the class OrderQuantityPackageShipService ? As I look at it you have a getter and setter for each attribute of the class Package. Are these getters and setters really needed ? Having getters/setters for all those attributes doesn't go well with encapsulation.
Can you think of providing public methods in Package class that operate at a higher level and don't expose the internal attributes ? Wouldn't that help ?

Categories