error: Private access in class - java

public class ProductionWorker extends Employee
{
private int shift;
private double rateOfPay;
private double hoursWorked;
ProductionWorker(String name, int id, int shift, double rateOfPay, double hoursWorked)
{
super(name, id);
this.shift = shift;
this.rateOfPay = rateOfPay;
this.hoursWorked = hoursWorked;
}
public class TeamLeader extends ProductionWorker
{
private double monthlyBonus;
TeamLeader(String name,int id, int shift, double rateOfPay, double hoursWorked, double monthlyBonus)
{
super(name, id , shift, rateOfPay, hoursWorked);
this.monthlyBonus = monthlyBonus;
}
public double calcPay()
{
double pay = 0;
//night shift
if (shift == 2)
{
pay = ((hoursWorked + hoursWorked / 2) * rateOfPay) + monthlyBonus;
}
else
{
pay = (hoursWorked * rateOfPay) + monthlyBonus;
}
return pay;
}
}
I extend the class ProductionWorker to class TeamLeader then create a method calcPay() on the class TeamLeader my problem is I need to get the value of variable shift, hoursOfWorked and rateOfPay from the class ProductionWorker so i can use the method calcPay() to my main.Can anybody help me, thank you in advance.

To gain access to the variables of parent class (ProductionWorker), you need to change the variable scope from private to protected.
Private variables are visible only within the class.
Protected variables are visible in subclasses and to all classes within the package
You may refer to this link : http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html.
If you do not wish to set them as protected, you can create getters and setters for the variables too, but that is not the preferred way to go.
eg of getter and setter:
private int shift;
protected int getShift() {
return this.shift;
}
protected void setShift(int shift) {
this.shift = shift;
}

Because your fields are private that means that unless you create a method that returns the particular value you are looking for when the Object is instantiated, none of your other classes or their methods will be able to access that data, hence it being private.
What you need to do is create "getter" methods in your ProductionWorker class that will allow you to say something like this in your TeamLeader class:
shift = ProductionWorker.getShift();
These sorts of methods are specifically designed so that if you need to look at the fields of the Object from a different class, you can simply create the object and use its method to return the value. Here is what these methods should look like:
public int getShift()
{
return shift;
}
public double getHoursWorked()
{
return hoursWorked;
}
public double getRateOfPay()
{
return rateOfPay;
}
By putting these public methods in your superclass, you will be able to create a ProductionWorker in your TeamLeader subclass and use its methods to access the instance variables.
UPDATE
Here is some sample code that may work for your cause:
public class ProductionWorker extends Employee
{
private int shift;
private double rateOfPay;
private double hoursWorked;
ProductionWorker(String name, int id, int shift, double rateOfPay, double hoursWorked)
{
super(name, id);
this.shift = shift;
this.rateOfPay = rateOfPay;
this.hoursWorked = hoursWorked;
}
// Now we can add the "getters"
public int getShift()
{
return shift;
}
public double getHoursWorked()
{
return hoursWorked;
}
public double getRateOfPay()
{
return rateOfPay;
}
public class TeamLeader extends ProductionWorker
{
ProductionWorker prodWorker = new ProductionWorker(Jared, 10046, 2, 8.50, 12.6); // Creates a production worker you can reference
private int shift = prodWorker.getShift();
private double rateOfPay = prodWorker.getRateOfPay();
private double hoursWorked = prodWorker.getRateOfPay();
// These three statements demonstrate the getters and how they can be implemented
private double monthlyBonus;
TeamLeader(String name,int id, int shift, double rateOfPay, double hoursWorked, double monthlyBonus)
{
super(name, id , shift, rateOfPay, hoursWorked);
this.monthlyBonus = monthlyBonus;
}
public double calcPay()
{
double pay = 0;
//night shift
if (shift == 2)
{
pay = ((hoursWorked + hoursWorked / 2) * rateOfPay) + monthlyBonus;
}
else
{
pay = (hoursWorked * rateOfPay) + monthlyBonus;
}
return pay;
}
}
Keep in mind that this may not be the perfect solution for your entire project, as I cannot see the other superclass you are extending from or what your client should do with this code. This sample code is just meant to give you an idea of how getters work in classes that make Objects and demonstrate how they can be used. I would definitely keep the getters I set for you.
Also
Make sure that for every instance variable you have for an Object, you should have a getter for each one. You will find you might need to access that data from time to time to make calculations in a client.

Related

Using a single parameter from a Super class where the super class uses more parameters

this might be something really easy to address but I am really new to Java and I am having a problem fixing this error. I am working on a basic ATM Machine (I can't go fancy just yet). I have a BankAccount class, a Checking Account (extends bankAccount), A savingsAccount class (also extends bankAccount) and a User class. In my CheckingAccount class, I want to use one of the parameters from my SUPER class (bankAccount), "balance" but I am not sure if there is a way to only use ONE parameter from a constructor that has more than One parameter. If so, any clue for how to? I am getting an Error : "no suitable constructor found for BankAccount(double)..." . This is my code so far, I appreciate your help.
-- BankAccount Class --
package atm;
public class BankAccount {
public double balance;
public int accountNumber = 333220;
public User user;
public BankAccount(){
balance = 0;
}
public BankAccount(double balance, int accountNumber, User user){
this.balance = balance;
this.accountNumber = accountNumber;
this.user = user;
}
public void accountNumber(){
accountNumber++;
}
public int getAccountNumber(){
return accountNumber;
}
public void deposit (double amount){
balance += amount;
}
public void withDraw(double amount) {
balance -= amount;
}
public double getBalance (){
return balance;
}
public void transfer( BankAccount other,double amount){
withDraw(amount);
other.deposit(amount);
}
}
-- CheckingAccount Class --
package atm;
public class CheckingAccount extends BankAccount {
private int transactionCount;
private static final double transactionFees = 1.50;
private static final int freeTransactions = 5;
public CheckingAccount (double balance){
super(balance); //HERE is where I am confused. I only need to use the "balance"
transactionCount = 0;
}
public void deposit(double amount){
transactionCount ++;
super.deposit(amount);
}
public void withDraw(double amount){
transactionCount ++;
super.withDraw(amount);
}
public void deductFees (){
if (transactionCount > freeTransactions){
double fees = transactionFees * (transactionCount - freeTransactions);
super.withDraw(fees);
}
transactionCount = 0;
}
}
Thanks a lot!
You need to create another constructor in BankAccount.java that only initializes amount like below
public BankAccount(double balance){
this.balance = balance;
}
Read about having multiple constructors in Java here
http://tutorials.jenkov.com/java/constructors.html
Since CheckingAccount is a BankAccount, it must have all the attributes of the BankAccount, including the account number and the User who owns it.
The base class requires accountNumber and user to be supplied by the derived class, so you should change the constructor to forward this information to super:
public CheckingAccount (double balance, int accountNumber, User user){
super(balance, accountNumber, user);
transactionCount = 0;
}
Note 1: In certain situations a derived class could hard-code parameters to be passed to super; this is not one of these situations.
Note 2: Consider making BankAccount abstract, and changing accessibility of its constructor from public to protected.

Chaining multiple constructors

I understand that when chaining constructors this must be done on the first line of the main constructor, can someone explain how you would go about the below code.
I want to chain to all constructors so that they can all be private other than the main constructor.
public class Flight {
int passengers = 0;
int seats = 150;
double maxKgPerPassenger;
private Flight(int passengers) {
this.passengers = passengers;
}
private Flight(int seats) {
this.seats = seats;
}
private Flight(double maxKgPerPassenger) {
this.maxKgPerPassenger = maxKgPerPassenger;
}
public Flight(int passengers, int seats, double maxKgPerPassenger) {
this(passengers);
this(seats);
this(maxKgPerPassenger);
}
}
A constructor is up to set as many fields as possible or construct an instance completely.
You pick a constructor which has a greater number of arguments and use it within constructors with a smaller amount. For example,
public Flight(double maxKgPerPassenger) {
this(0, 0, maxKgPerPassenger); // default, default, maxKgPerPassenger
}
private Flight(int passengers, int seats, double maxKgPerPassenger) {
this.passengers = passengers;
this.seats = seats;
this.maxKgPerPassenger = maxKgPerPassenger;
}
I want to chain to all constructors so that they can all be private other than the main constructor.
I suggest the opposite way. Make all constructors you are going to use public, but an all-arguments constructor private if you won't be using that.
The approach you tried to adopt is similar to the builder pattern where each method sets a single field. You definitely need to have a look at it if a number of arguments are going to grow up.
Why do you want to chain constructors ?
As you chain constructors, you have to specify some default values from the constructor with less argument to the invoked constructor with more arguments.
You do the reverse here :
public Flight(int passengers, int seats, double maxKgPerPassenger){
this(passengers);
this(seats);
this(maxKgPerPassenger);
}
You indeed want to invoke from the constructor with the most argument all other constructors.
It makes no sense and it is not valid either as a constructor can invoke a single other constructor of the same class.
I want to chain to all constructors so that they can all be private
other than the main constructor.
Things work in the reverse order.
The actual code doesn't seem to need constructor chaining.
This one is enough :
public Flight(int passengers, int seats, double maxKgPerPassenger){
this.passengers = passengers;
this.seats = seats;
this.maxKgPerPassenger = maxKgPerPassenger;
}
Suppose that class clients could create Flight instances with two flavors :
by passing all parameters
by passing only the seats parameter (remains being valued with default values)
You could so write :
public Flight(int passengers, int seats, double maxKgPerPassenger){
this.passengers = passengers;
this.seats = seats;
this.maxKgPerPassenger = maxKgPerPassenger;
}
public Flight(int seats){
super(50, seats, 10); // you pass some default values for passengers and maxKgPerPassenger
}
make the default constructor private to prevent constructor instantiation and instantiate objects using a public static method. This way you can work around the constructor restriction. To add a little confusion I converted your constructors to normal methods using the class name by adding void return type. Also consider if want you really want isn't the Builder pattern.
public class Flight {
private int passengers = 0;
private int seats = 150;
private double maxKgPerPassenger;
private Flight() {}
private void Flight(int passengers)
{
this.passengers = passengers;
}
private void Flight(int seats)
{
this.seats = seats;
}
private void Flight(double maxKgPerPassenger)
{
this.maxKgPerPassenger = maxKgPerPassenger;
}
public static Flight create(int passengers, int seats, double maxKgPerPassenger)
{
Flight flight = new Flight();
flight.Flight(passengers);
flight.Flight(seats);
flight.Flight(maxKgPerPassenger);
return flight;
}
}

Is my constructor efficient?

For a programming assignment, I am asked to write
"a) A generic constructor that takes no values. This constructor lets you use the account with all the fields set to their default values.
b) A constructor that takes five inputs. The first is a double and is the interest rate for the account, the second is a int as is the minimum balance for the account, the third is a double and is the overdraft fee for the account, the fourth is a double and is the ATM fee for the account, and the fifth is a double and is the bounced check fee for the account."
I am afraid that my code is redundant and inefficient. I was hoping someone would tell me what is unnecessary and/or if I am missing anything important. How can I create the generic constructor without manually initializing the fields? Also, I'm a bit worried that my second constructor does not initialize any fields besides the 5 listed as parameters.
public class BankAccount
{
/*Balance of BankAccount*/
private double balance = 0.00;
/*Minimum balance allowed for BankAccount*/
private int minimumBalance = 0;
/*Interest rate of BankAccount*/
private double interestRate = 0.00;
/*Fee given everytime withdrawal is made via ATM*/
private double ATMFee = 0.00;
/*Amount deducted from balance if there is an overdraft*/
private double overdraftFee = 0.00;
/*Number of withdrawals allowed to be made before fee*/
private int withdrawLimit = 0;
/*Value to be deducted from balance if withdrawal limit is exceeded*/
private double withdrawFee = 0.00;
/*Keeps track of how many withdrawals owner has made*/
private int withdrawCount = 0;
/*Fee for bouncing a check*/
private double bouncedCheckFee = 0.00;
/*Stores interest earned*/
private double interestEarned = 0.00;
/*Whether or not overdraft fee has been charged*/
private boolean overdraftFlag = false;
/*Generic constructor takes no parameters and initializes field values to their default values*/
public BankAccount()
{
this.balance = balance;
this.minimumBalance = minimumBalance;
this.interestRate = interestRate;
this.ATMFee = ATMFee;
this.overdraftFee = overdraftFee;
this.withdrawLimit = withdrawLimit;
this.withdrawFee = withdrawFee;
this.withdrawCount = withdrawCount;
this.bouncedCheckFee = bouncedCheckFee;
this.interestEarned = interestEarned;
this.overdraftFlag = overdraftFlag;
}
/*More specialized constructor takes 5 fields as parameters and initalizes them to their specified values*/
public BankAccount(double interestRate, int minimumBalance, double overdraftFee, double ATMFee, double bouncedCheckFee)
{
this();
this.interestRate = interestRate;
this.minimumBalance = minimumBalance;
this.overdraftFee = overdraftFee;
this.ATMFee = ATMFee;
this.bouncedCheckFee = bouncedCheckFee;
}
}
EDIT: Okay I edited my code according to everyone's advice.
Here it is. Is it good now?
public class BankAccount
{
/*Balance of BankAccount*/
private double balance = 0.00;
/*Minimum balance allowed for BankAccount*/
private int minimumBalance = 0;
/*Interest rate of BankAccount*/
private double interestRate = 0.00;
/*Fee given everytime withdrawal is made via ATM*/
private double ATMFee = 0.00;
/*Amount deducted from balance if there is an overdraft*/
private double overdraftFee = 0.00;
/*Number of withdrawals allowed to be made before fee*/
private int withdrawLimit = 0;
/*Value to be deducted from balance if withdrawal limit is exceeded*/
private double withdrawFee = 0.00;
/*Keeps track of how many withdrawals owner has made*/
private int withdrawCount = 0;
/*Fee for bouncing a check*/
private double bouncedCheckFee = 0.00;
/*Stores interest earned*/
private double interestEarned = 0.00;
/*Whether or not overdraft fee has been charged*/
private boolean overdraftFlag = false;
/*Generic constructor takes no parameters and initializes field values to their default values*/
public BankAccount()
{
}
/*More specialized constructor takes 5 fields as parameters and initalizes them to their specified values*/
public BankAccount(double interestRate, int minimumBalance, double overdraftFee, double ATMFee, double bouncedCheckFee)
{
this.interestRate = interestRate;
this.minimumBalance = minimumBalance;
this.overdraftFee = overdraftFee;
this.ATMFee = ATMFee;
this.bouncedCheckFee = bouncedCheckFee;
}
}
In your constructor with no arguments, you re-assign the values of your fields, which is superflous. If you already give them a value in the declaration, you don't need to do it again in the constructor if you don't want it to have a different value.
First off, your default BankAccount() constructor should be empty. It's just assigning the fields to themselves.
Second, please only include mandatory fields in your constructor. See my answer here and either use setters after creation or use the Builder Pattern to build out your object using optional parameters.
Hope this helps!
The default constructor repeat fields initialization that is already present in the field declarations. You can simply clean its body.
Another limit to your code is that when you have to create an object, you have to specify all the fields used in the constructor. You can avoid this, using the fluent interface and builder pattern to get code more readable.
Now i translate what i said in code.
The code for the BankAccountOptions class:
public class BankAccountOptions {
public static BankAccountOptions build() {
return new BankAccountOptions();
}
public double aTMFee;
public double balance;
public double bouncedCheckFee;
public double interestEarned;
public float interestRate;
public int minimumBalance;
public double overdraftFee;
public boolean overdraftFlag;
public int withdrawCount;
public double withdrawFee;
public int withdrawLimit;
public BankAccountOptions aTMFee(double value) {
aTMFee = value;
return this;
}
public BankAccountOptions balance(double value) {
balance = value;
return this;
}
public BankAccountOptions balance(int value) {
minimumBalance = value;
return this;
}
public BankAccountOptions bouncedCheckFee(double value) {
bouncedCheckFee = value;
return this;
}
public BankAccountOptions interestEarned(double value) {
interestEarned = value;
return this;
}
public BankAccountOptions interestRate(float value) {
interestRate = value;
return this;
}
public BankAccountOptions overdraftFee(double value) {
overdraftFee = value;
return this;
}
public BankAccountOptions overdraftFlag(boolean value) {
overdraftFlag = value;
return this;
}
public BankAccountOptions withdrawCount(int value) {
withdrawCount = value;
return this;
}
public BankAccountOptions withdrawFee(double value) {
withdrawFee = value;
return this;
}
public BankAccountOptions withdrawLimit(int value) {
withdrawLimit = value;
return this;
}
}
The class BankAccount
public class BankAccount {
/* Fee given everytime withdrawal is made via ATM */
private double ATMFee;
/* Balance of BankAccount */
private double balance;
/* Fee for bouncing a check */
private double bouncedCheckFee;
/* Stores interest earned */
private double interestEarned;
/* Interest rate of BankAccount */
private double interestRate;
/* Minimum balance allowed for BankAccount */
private int minimumBalance;
/* Amount deducted from balance if there is an overdraft */
private double overdraftFee;
/* Whether or not overdraft fee has been charged */
private boolean overdraftFlag;
/* Keeps track of how many withdrawals owner has made */
private int withdrawCount;
/* Value to be deducted from balance if withdrawal limit is exceeded */
private double withdrawFee;
/* Number of withdrawals allowed to be made before fee */
private int withdrawLimit;
/* Generic constructor takes no parameters and initializes field values to their default values */
public BankAccount() {
this(BankAccountOptions.build());
}
BankAccount(BankAccountOptions options)
}
/* More specialized constructor takes 5 fields as parameters and initalizes them to their specified values */
public BankAccount(BankAccountOptions options) {
balance = options.balance;
minimumBalance = options.minimumBalance;
interestRate = options.interestRate;
ATMFee = options.aTMFee;
overdraftFee = options.overdraftFee;
withdrawLimit = options.withdrawLimit;
withdrawFee = options.withdrawFee;
withdrawCount = options.withdrawCount;
bouncedCheckFee = options.bouncedCheckFee;
interestEarned = options.interestEarned;
overdraftFlag = options.overdraftFlag;
}
}
Now suppose you want to create a BankAccount object with default values. The code will be:
...
BankAccount account=new BankAccount();
...
If you want to create an account and modify only two attributes (i.e. minimumBalance and withdrawLimit) you can write:
...
BankAccount account=new BankAccount(BankAccountOptions.build().minimumBalance(200).withdrawLimit(4));
...

Undefined Constructor error

Am trying to implement a system for a car dealer, but when I try to instantiate my Car class in a derived class, I get the error message
Multiple markers at this line
- The constructor Car(String, int, String, String, double, double) is
undefined
Here's the parent class Car:
package Number3;
public class Car {
private String plateNum;
private int year;
private String make;
private String model;
protected double costPrice;
protected double sellingPrice;
public Car()
{
plateNum = "";
year = 1990;
make = "";
model = "";
costPrice = 0.0;
sellingPrice = 0.0;
}
public Car(String plateNum,int year,String make,String model,double costPrice,double sellingPrice)
{
this.plateNum = plateNum;
this.year = year;
this.make = make;
this.model = model;
this.costPrice = costPrice;
this.sellingPrice = sellingPrice;
}
public double getCostPrice()
{
return costPrice;
}
public double computeSellPrice()
{
sellingPrice = costPrice;
return sellingPrice;
}
public void displayCarDetails()
{
System.out.println("Plate number: "+plateNum);
System.out.println("Year: "+year);
System.out.println("Make: "+make);
System.out.println("Cost price: "+costPrice);
System.out.println("Selling price: "+sellingPrice);
}
}
and the subclass newCar:
package Number3;
public class newCar extends Car{
private double tax;
public newCar(String plateNum,int year, String make, double costPrice, double sellingPrice, double tax)
{
super(plateNum,year,make,costPrice,sellingPrice); //where the error is found
this.tax = (25/100);
}
public double computeSellPrice()
{
sellingPrice = costPrice + (costPrice * tax);
return sellingPrice;
}
public void displayCarDetails()
{
super.displayCarDetails();
}
}
Any help would be appreciated.
The signature of your Car constructor does not match the signature in the derived class.
In your Car class, this is the constructor:
public Car(String plateNum,int year,
String make,String model,double costPrice,double sellingPrice) {
...
}
It is String, int, String, String, double, double)
While in the derived class:
you have:
super(plateNum,year,make,costPrice,sellingPrice)
Which is int, int, String, double, double
Change the arguments in call to Super in your newCar class to match the constructor of your Car class. That is, in your newCar class, the line
super(plateNum,year,make,costPrice,sellingPrice)
should be :
super(plateNum, year,
make, model, costPrice, sellingPrice)
The Car class does not have a constructor that takes 5 parameters.
It is defined as
public Car(String plateNum,int year,String make,String model,double costPrice,double sellingPrice)
{
...
}
and you're trying to call it without passing the model parameter.
super(plateNum,year,make,costPrice,sellingPrice); //where the error is found
Your super/parent class Car has a no-argument constructor public Car() { and the following 6-parameter constructor which is being called from the sub/child class constructors using the keyword super.
public Car(String plateNum,int year,String make,String model,double costPrice,double sellingPrice)
Notice, that it expects String model as its fourth parameter but your public newCar() constructor is passing it only five parameters. The parameter model is missing.
public newCar(String plateNum,int year, String make, double costPrice, double sellingPrice, double tax)
{
super(plateNum,year,make,costPrice,sellingPrice); // model MISSING!
So, to fix it, either modify the constructor to accept model as well (just like in your usedCar() constructor) or pass null to the super class constructor as
super(plateNum,year,make,null,costPrice,sellingPrice); // model = null

how would I use an if statment to change the value of an attribute?

I want to be able to give a specific value to discount depending on certain requirements like the following age: > 25 and profession = teacher / professor get 10% discount, age < 25 and gradepoint > 7 get 25% discount
this is my code so far I am using double OO paradigm:
public class customer {
//attribute definitions
private String name;
private String address;
private String profession;
private Integer age;
private Integer gradepoint;
private double discount;
//constructor
public customer(String newName, String newAddress, String newProfession, Integer newAge, Integer newGradepoint, double newDiscount)
{
setName(newName);
setAddress(newAddress);
setProfession(newProfession);
setAge(newAge);
setGradepoint(newGradepoint);
setDiscount (newDiscount);
}
//getters
public String getName()
{ return name;}
public String getAddress()
{ return address;}
public String getProfession()
{ return profession;}
public Integer getAge()
{ return age;}
public Integer getGradepoint()
{ return gradepoint;}
public double getDiscount()
{ return discount;}
//setters
public void setName (String newName)
{ name = newName;}
public void setAddress (String newAddress)
{ address = newAddress;}
public void setProfession (String newProfession)
{ profession = newProfession;}
public void setAge (Integer newAge)
{ age = newAge;}
public void setGradepoint (Integer newGradepoint)
{ gradepoint = newGradepoint;}
public void setDiscount (double newDiscount)
{ discount = newDiscount;}
//methods
}
Would I need to create a sub class called discount or each type of discount? or I can write a method directly into this customer class to control the discount?
write a method directly into this customer class to control the discount?
This. Make it a calculated field. Kill setDiscount function, kill discount variable, and make the getDiscount function into something like:
public double getDiscount() {
if (...) return ...;
if (....) return ...;
...
}
...unless you want to have this as the default discount, and still allow modification, in which case keep discount as a property, and move this whole logic into the constructor, having conditional setDiscount() calls.
Your getDiscount function would ideally do the calculation and return the appropriate discount for the current object. For example:
public double getDiscount()
{
if (getAge() < 25 && getGradepoint() > 7)
{
return .25;
}
else if // other logic...
}
Although not the simplest solution, I would abstract the discount calculation to a separate interface and class as well as having an override discount value in the customer object.
E.g.
public interface DiscountManager<T>
{
public double getDiscount(T discountObject);
}
public abstract class AbstractCustomerDiscountManager extends DiscountManager<Customer>
{
public double getDiscount(Customer customer)
{
if (customer.hasCustomDiscount()) { return customer.getDiscount(); }
else { return calculateDiscount(customer); }
}
public abstract double calculateDiscount(Customer customer);
}
public class DefaultDiscountManager extends AbstractCustomerDiscountManager
{
public double calculateDiscount(Customer customer)
{
double discount = 0;
if ((customer.getAge() != null) && (customer.getAge() < 25)) { discount += 25; }
...
return discount;
}
}
Probably over time different rules evolve. At the spot where the discounting takes place, in the order, the discount and and a reference to the rule applied should be stored together.
This kind of business logic could have its own class. A generic solution would even be to store the rule as scriptable code (BeanShell = Java, or JavaScript) and use java's scripting API. So that this kind of business logic resides more with the business managers, and the rules can be presented and edited.

Categories