Java - Method declared but cannot reference it - java

I am kind of new to Java, although I've programmed in other procedural langauages for 25 years. So, I'm trying to teach myself Java. Trying to write some silly program consisting of two files: a Class called "Customer", and a main program called "Silly4".
I'm pretending to implement a credit card system for a bank type company (even though the majority of my experience was in defense contracting). I figure this would be a good teaching example for me.
Trying to build a credit card data structure called "Customer" such that (for the time being) it can accomodate 1000 customers. In the main program "Silly4", I instantiate this Customer class as "cust2", and then from there I attempt to work with "cust2". I try to retrieve customer number 5's (j=5) credit card balance. So far, so good.
Then from there I attempt to declare in the class Customer another method (for future use) which I arbitrarily call "bal44", and then I attempt to reference it in the main program Silly4 as " ball44(5541);".
So I compile class Customer, then compile program Silly4, and I'm getting a compile error "java:52: error: cannot find symbol" for the reference to method "bal44(5541)" in main program "Silly4". I'm confused. I've declared and successfully compiled the class Customer with "bal44" in there, but Java is telling me it can't find it. I'm confused.
Please excuse all the extraneous println's, I use them to see how the program is moving along.
Here is class Customer:
// Data Structure for credit card database
public class Customer {
private String name;
private int accountNo;
private double balance;
private boolean Overdue;
// Getters, setters, constructor...
public void setName( String new_name )
{ name = new_name; }
public void setAccount( int new_account )
{ accountNo = new_account; }
public void setBalance( double new_bal )
{ System.out.println( " Start proc setBalance ");
balance = new_bal;
System.out.println( " Finish proc setBalance ");
}
public double getBalance()
{ System.out.println( " Start proc getBalance ");
System.out.println( " proc getBalance , balance= " + balance + " end print");
return balance;
// how to specify which element of array[1000] ? balance I want ?
// System.out.println( " Finish proc getBalance ");
}
// Add new customer to credit card system
// (note - index in array Customer[i] is worry of main program
//
public void addCustomer( String name2, int account2, double bal2 )
{ name = name2;
accountNo = account2;
balance = bal2;
}
public void bal44 ( int account3 )
{ accountNo = account3; }
// Constructor
Customer ()
{ name = "John Smith";
accountNo = 1005;
balance = 125.43;
Overdue = false; }
// see page 1032 Liang for definition complex Object and get-Procs for it
}
Here is main program/class Silly4:
class Silly4
{
// Program for credit card database
public static void main(String[] args)
{
double bal2, bal3;
int i; // loop counter
int j;
bal2 = 151.47;
bal3 = 5.0; // just initialize
// And then you can create an array of it:
System.out.println("** Program Silly4 Running **");
Customer[] cust2 = new Customer[1000];
System.out.println("** Array cust2 instantiated **");
for(i=0; i<=999; ++i)
{
cust2[i] = new Customer();
}
System.out.println("** Array2 cust2 Obj initialized **");
// try to code this eventually - cust2.balance = 151.47 ;
//
j = 5; // customer no. 5
cust2[j].setBalance( bal2 );
bal3 = cust2[j].getBalance() ;
System.out.println("** Balance Customer " + j + " is " + bal3);
// Add a new customer
// comment out - addCustomer( "Steve Jones", 5541, 1.0 );
bal44( 5541 ); // test out declaring new method "bal44"
System.out.println("** End of Silly4 **");
}
}

You basically answered yourself in the first sentence of your query. Java is not a purely procedural language, it's an object-oriented language.
That means that when you declare methods, they are not just scoped functions. A method declared in a class is not similar to a function declared in an included file in C. It's something that can be only called from the scope of an object of the enclosing class. In other words, you don't have a function named bal44. You have a method bal44 of class Customer, which means that you need to ask an object fo class Customer to execute it for you, similar to how you call setBalance().
EDIT: As another comment mentions, what might be confusing you more is that whenever you use a method name without qualifiers, Java treats it as a shortcut of asking this (the current object) to execute the method, so technically, method(args) is a shortcut for this.method(args). Therefore, whenever you are within the scope of a single class, a class's methods will behave almost as traditional functions.

When you call
bal44( 5541 );
Without any object, Java assumes it as a "this" object and searches for that method in Silly4 not in Customer class. Call that method from Silly4 like you are calling other method of customer class.
e.g.
cust2[j]. bal44( 5541 ); or something like that.
Read more about "this" here https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html
P.S. A bonus point to note here is that static method's like main method do not have this reference available to them. So, technically here it is searching for a class-level(static) method in Silly4 rather than instance method. :)

See, here is the problem : You are using the bal44(5541), but you made that method non static, meaning you need to make an object of your class (Customer) and then say for example
Customer customer = new Customer()
customer.bal(5541);
If you want to call that method without making an object of its class, simply put the keyword "static" in the method's header. public static void bal44(int num)
Further explanation : Since you are from a procedural language, recall the main difference is the usage of objects. An object is something that has several traits, or attributes, and actions or behaviors. For example a car, its attributes are its color, speed, etc. and its main action/behavior is drive. Attributes are variables, and Behaviors/Actions are methods. e.g.
car.drive();
car.setColor("red");
I hope that helped? If you don't understand you can PM me or respond here and I'll explain in further detail

Related

Java constructor creates many null instances before the required object

this is my first question on here and I did a search before forming it, so I hope everything is as required.
I am working on a school assignment in Java. I am able to produce the required output but there are a lot of null instances created first. I don't understand why. Information about the library the professor created for the course and the code are below
Library included with this course: i2c.jar. It can be found here.
included in this Library are the classes Country and CountryDB. The API for the Country class can be found at http://130.63.94.24/~roumani/book/doc/i2c/ca/roumani/i2c/Country.html
The API for the CountryDB class can be found at http://130.63.94.24/~roumani/book/doc/i2c/ca/roumani/i2c/CountryDB.html
I am asked to create a class called Game, using the Country and CountryDB APIs.
The only attribute is db, which is an instance of CountryDB.
The constructor only sets the attribute (db) for this instance to a new CountryDB object.
The class is also meant to include a method (called qa) that follows this pseudocode:
get a reference to the database's capital city list
determine the size of this list. Cal it n.
generate a random number in [0,n) called index.
invoke get(index) on the list to get a random capital city. Call it c
get a reference to the database's data map
invoke get(c) on the map to get a reference to a country. Call it ref.
The method is then supposed to return one of two Strings (which will be clear in the code). Everything works as it should, except I get a lot of "nulls" before the desired output. When made into a List, db has size 241 so I suspect I am creating 241 null instances and 1 proper instance. I have no idea why though. I have tested every line of code in my method and the constructor was dictated by the textbook.
CODE
package ca.yorku.eecs.caps;
import java.util.List;
import java.util.Map;
import ca.roumani.i2c.Country;
import ca.roumani.i2c.CountryDB;
public class Game
{
private CountryDB db;
public Game()
{
this.db = new CountryDB();
}
public String qa()
{
List<String> capitals = db.getCapitals();
System.out.println(capitals.toString());
int n = capitals.size();
System.out.println(n);
int index = ((int) (n * Math.random()));
System.out.println(index);
String c = capitals.get(index);
System.out.println(c);
Map<String, Country> data = db.getData();
Country ref = data.get(c);
if (Math.random() > 0.5)
{
return "What is the capital of " + ref.getName() + "? \n" + ref.getCapital();
}
else
{
return ref.getCapital() + " is the capital of? \n" + ref.getName();
}
}
public static void main(String[] args)
{
Game g = new Game();
System.out.println(g.qa());
}
}
the System.out.println() statements are only there to test when the nulls occur. It clearly happens immediately because my psvm output is 241 nulls (on separate lines) followed by my desired output. Can somebody please tell me what I am doing wrong?
And, more generally (to help more people) how do you implement classes, the constructor of which instantiates another class and sets it as an attribute value?
I appreciate any help. Also, please note, I am not trying to get others to do my work for me. I've spent hours on this and my lab TA also wasn't sure why it happens either. He would have helped me correct it had he known how.
Thank you.

Why can't the second class get variable data from third class?

I am having a problem with passing of variables between classes.
The problem that I am having is that the second class is not obtaining the variable data from the third class after first class sets the value to teh variables in third class.
The way in which I would like it to work is that I have one class (classA) where it obtains the value from the user and calls the set method is the third class to set the value to the variable, second class (classB) will be used get the value using the get method in the third class and the third class (ClassC) is where get and set methods resides.
ClassA method coding:
//method for 'add' button functionality
public void btnAddActionPerformed(java.awt.event.ActionEvent evt)
{
ArrayList<UserInfo> userobjList = new ArrayList<>();
//calling data field revelant text fields
int EmpNumber = Integer.parseInt(txtEmpNum.getText());
String EmpAccessType = txtAccessType.getText();
//creating the object to parse data to userinfo class
UserInfo user = new UserInfo(EmpNumber, EmpAccessType);
//setting the data to varibales in userinfo class
user.setEmpNumber(EmpNumber);
user.setEmpAccessType(EmpAccessType);
//adds the object to the arraylist
userobjList.add(user);
//creates the object to use the method for adding employee to system
AddEmpFunction addUser = new AddEmpFunction();
addUser.test();
}
This class obtains user information and sets the data in the third class
ClassB method for adding user to system coding:
//variables
int EmpNumber;
String AccessTypes;
//creation of object to be used throughout
UserInfo user = new UserInfo(EmpNumber, AccessTypes);
public void AddNewEmpLogin()
{
try
{
//SQL string command to be executed to add user login details
String addNewUserLogin = "insert into userLoginData(Username, accessType) values ("
+ user.getEmpNum() + ","
+ quotate(user.getEmpAccessType()) + ")";
//create the statement that will be used
Statement stmt=conn.createStatement();
//executes the addNewUser statement
stmt.executeUpdate(addNewUserLogin);
}
catch (Exception e)
{
//exception error message is shown
JOptionPane.showMessageDialog(null, "Error adding new User's details \n " + e, "Database Error", JOptionPane.ERROR_MESSAGE);
}
}
This class is where the data will be obtained from third class and then stored in MySQL.
ClassC is where the get and set methods are:
private int EmpNumber;
private String EmpAccessType;
//constructor
public UserInfo(int EmpNumber, String EmpAccessType)
{
this.EmpNumber = EmpNumber;
this.EmpAccessType = EmpAccessType;
}
public int getEmpNum()
{
return EmpNumber;
}
public void setEmpNum(int EmpNum)
{
this.EmpNumber = EmpNum;
}
public String getEmpAccessType()
{
return EmpAccessType;
}
public void setEmpAccessType(String EmpAccessType)
{
this.EmpAccessType = EmpAccessType;
}
The data is passing perfectly well from classA to classC but the data returned in classB whcih calls it up form classC displays null for the string and 0 for the integer.
Please could someone please explain where my problem is and how I can fix this. I have read a lot about get and set methods and there is no actualy example for what I am trying to achieve.
Any help will be much appreciated. :)
Because you have two different instances of the third class. You're doing this in one place (variable names changed to illustrate):
UserInfo userA = new UserInfo();
userA.setEmpNumber(EmpNumber);
userA.setEmpAccessType(EmpAccessType);
And then this in another:
UserInfo userB = new UserInfo();
userB.getEmpNumber();
userB.getEmpAccessType();
So you set data on one object, and then try to get that data from another object. But you can't, because no data was ever set on that object.
As an analogy, consider two identical cars. Same make, same model, came off the same production line. You are putting gas into one car, then trying to drive the other one. But you can't. Because it doesn't have any gas in it.
You need to use the same instance of the object:
UserInfo user = new UserInfo();
user.setEmpNumber(EmpNumber);
user.setEmpAccessType(EmpAccessType);
// ...
user.getEmpNumber();
user.getEmpAccessType();
If your second class needs a valid instance of your third class in order to perform its task, then it should require that as a constructor parameter. So when the first class holds that user variable and then creates an instance of the second class, it passes the user variable to that instance. So there's only one user.
(Additionally, as a side note, you don't need to pass the values to the constructor and use the setters. One or the other is fine. A value only needs to be set once.)
int EmpNumber;
String AccessTypes;
//creation of object to be used throughout
UserInfo user = new UserInfo(EmpNumber, AccessTypes);
You set up new user with no field filled.
And then you
+ user.getEmpNum() + ","
+ quotate(user.getEmpAccessType()) + ")";
from your empty user so it returns 0 and null respectively.
Pass your user from classA to classB first?
Your class B does not seem to receive data from class A.
Class C, UserInfo is a data store object (POJO) but the instance user that is created in class A is never passed to class B in your sample code.
As a matter of fact, class B seems to create its own instance of UserInfo with empty values.
So, to keep this short: pass the user object from class A to B, for example by using AddEmpLogin( UserInfo user ).
Next, read a solid introduction to object-oriented programming.

Overriding and Inheritance

i am having problems with my codes. this is our assignment:
"Write a superclass named clsWorker and subclasses clsHourlyWorker and clsSalariedWorker. Every worker has a name and a salary rate. Write a method computePay(int hours) that computes the weekly pay for every worker. An hourly worker gets paid the hourly wage for the actual number of hours worked if hours is at most 40. If the hourly worker worked for more than 40 hours, the excess is paid at time and a half. The salaried worker gets paid the hourly wage for 40 hours, no matter what the actual number of hours is. Write a test program for the inheritance. Input the name of the worker, the number of hours worked and the type of worker, H for hourly and S for salaried, the salary rate of the worker. Display the salary of every worker entered."
we need to do overriding and inheritance. i always encounter the NoSuchMethodError
My superclass:
public class clsWorker
{
int hours=0,excess=0;
double salary,newSalary=0.0;
String sType;
public clsWorker()
{
}
public clsWorker(double sal,String type)
{
//this.hours=hours;
salary=sal;
sType=type;
}
public double computePay(int hours)
{
sType=sType.toUpperCase();
if(sType.equals("H"))
newSalary=(salary*hours)*7;
else if(sType.equals("S"))
{ if(hours>=40)
newSalary=salary*40;
else if(hours>40)
{
excess=hours-40;
newSalary=(newSalary+((newSalary*excess)*1.5))*7;
}
}
return newSalary;
}
}
My subclasses
public class clsHourlyWorker extends clsWorker
{
double dSalary=0.0;
int iHours=0;
public clsHourlyWorker()
{
//super();
}
public clsHourlyWorker(int iHours, double salaryph,String sRate)
{
super(iHours,salaryph,sRate);
//clsWorker w=new clsWorker();
dSalary=newSalary;
}
public double getSalary()
{
return dSalary;
}
}
public class clsSalariedWorker extends clsWorker
{
double dSalary=0.0;
int iHours=0;
public clsSalariedWorker()
{
//super();
}
public clsSalariedWorker(int iHours,double salaryph,String sRate)
{
super(iHours,salaryph,sRate);
//super(salaryph,sRate);
//this.iHours=iHours;
//clsWorker w=new clsWorker();
dSalary=newSalary;
}
/*public void setSalary(int iHourjs)
{
}*/
public double getSalary()
{
return dSalary;
}
}
my test class
import java.util.*;
public class testSalary
{
public static void main(String[]args)
{
Scanner console=new Scanner(System.in);
System.out.println("Input Salary per hour: ");
double salaryph=console.nextDouble();
System.out.println("Input number of hours: ");
int iHours=console.nextInt();
console.nextLine();
System.out.println("Input Worker Name: ");
String sName=console.nextLine();
System.out.println("Input Type of Worker: ");
String sRate=console.next();
clsHourlyWorker hw=new clsHourlyWorker(iHours,salaryph,sRate);
clsSalariedWorker sw=new clsSalariedWorker(iHours,salaryph,sRate);
//System.out.println("Worker Name: "+sName+"\nSalary: "+hw.getSalary());
if(sRate.equals("H"))
System.out.println("Worker Name: "+sName+"\nSalary: "+hw.getSalary());
else if (sRate.equals("S"))
System.out.println("Worker Name: "+sName+"\nSalary: "+sw.getSalary());
}
}
can someone tell me how to fix my problem? thanks.
This doesn't make sense:
public clsHourlyWorker(int iHours, double salaryph,String sRate)
{
super(iHours,salaryph,sRate);
//clsWorker w=new clsWorker();
dSalary=newSalary;
}
Since the super class's constructor doesn't take int, double, and String but rather, it takes String, double, int representing name, dRate, and hours. Also is sRate really supposed to be a String? I strongly doubt it.
I suggest that your child class constructor accept in the parameter all the information needed for the super constructor (a Strinng for name, double for dRate and int for hours) plus additional parameters the additional information for the new child class fields. You may wish to re-think those fields though as some seem to be duplicates of the super's fields and thus unnecessary.
A couple of things could be improved:
Use inheritance
Simply put, the code you posted does not leverage the power of inheritance at all. You created two subclasses, but all they do is delegate the payment computation back to the superclass. Make clsWorker abstract, make computePay abstract and implement two different versions of the method in the subclasses:
public abstract class Worker {
// ...
public abstract double computePay(int hours);
}
public class HourlyWorker extends Worker {
// ...
#Override
public double computePay(int hours) {
// code from the 'sType.equals("H")' block
}
}
public class SalariedWorker extends Worker {
// ...
#Override
public double computePay(int hours) {
// code from the 'sType.equals("S")' block
}
}
Now you will also realize that the field sType is not serving any useful purpose. In fact, this approach would be required only if polymorphism was not supported by Java. You already know (when writing the code) whether you're dealing with an HourlyWorker or a SalariedWorker because you put the code either in HourlyWorker's computePay or in SalariedWorker's computePay.
sType does not provide any new information that we would not already know from looking at the inheritance hierarchy. This way, you're giving the exact same information twice (once by inheritance, once by sType), which is something we're generally trying to avoid in software development.
Improve "test" class
(I put "test" in quotes because most developers would think that by "test" class, you mean some sort of automated, unit-testing "test" - e.g. a JUnit test case.)
First thing that seems odd is: Why instantiate both a HourlyWorker and a SalariedWorker (i.e. new clsHourlyWorker, new clsSalariedWorker), if the user can choose to either create a HourlyWorker or a SalariedWorker before (but not both, this is 'exclusive or')?
What you really want is something along the lines of:
Worker w;
if(sRate.equals("H"))
w = new HourlyWorker(iHours,salaryph);
else if (sRate.equals("S"))
w = new SalariedWorker(iHours,salaryph);
else
throw new Exception("Don't recognize worker type: " + sRate);
System.out.println("Worker Name: "+sName+"\nSalary: "+w.getSalary());
As you can see, it is valid to use the abstract superclass Worker as the type for your worker instance variable, w, if you don't know at this point (during runtime) whether the user will choose H or S. You only need to access getSalary, which is declared in Worker, so everyhing is fine. (If you ever later needed to access a method which is implemented only by a subclass, you could still type-cast it.)
You will also realize that you need only one println. Again, we'd like to minimize duplication in favor of abstraction. Both lines do basically the same, they print name and computed salary of a worker, so we try to reduce two lines to one, more abstract line of code.
Second, you might also, instead of printing sName directly, want to have a getter (getName) in Worker. When you get to work on larger projects, you'll see that input and output can happen at a very different time and place (e.g. Worker might be stored in a database and the original variable sName will be long gone when a different user retrieves the Worker from the database). So be prepared to get all required data from your real objects, not the test input.
Third - but I might be mistaken here - "Display the salary of every worker entered" sounds to me like you're supposed to implement a while loop where the user can enter multiple workers. But then, there are more important things you can learn from this assignment.
Follow naming conventions
In Java, it is very common practice to have uppercase class names and lowercase method names. Normally you'd have Worker, HourlyWorker and SalariedWorker (see code sample above). This way, every Java developer in the world can already tell we're talking about classes.
However, for your assignment, I'd suggest you follow whatever arbitrary "conventions" there are - just keep in mind that this is not the standard Java way. Read up on naming conventions (general and particular) before you do something like this in real-world projects.

JAVA questissn regarding methods/classes

I am somewhat new to JAVA. I've been working with it in college, but I have to admit, my instructor is of absolutely no help. She hardly knows JAVA herself, but that is another issue all in itself. I've been confused as to how methods and classes work. I'm creating this program that uses two files, one "main" file, and a "test" file. I can't seem to get the "main" file correct, as the compiler keeps telling me that it cannot find the symbols, even though they are. In the "test" file, I can't seem to get the compiler to recognize the methods from the "main" file. I have made sure that the files are in the same folder. I want to combine them into one file for simplicity, but I will lose points. I've included my code so far. I'm not looking for a "fix-it" solution, I just want to figure out why it's not working. ANY help is appreciated, since my instructor isn't of much assistance Thank you kindly!
MAIN FILE:
import java.util.Scanner;
class Fruit1 {
static Scanner console = new Scanner(System.in);
public static void main(String args[]) {
String color;
String taste;
}
public Fruit1() {
// generic constructor
color = "red";
taste = "yum";
}
public Fruit1(String aColor, String aTaste) {
// constructor with parameters
color = aColor;
taste = aTaste;
}
public Fruit1(String bColor, String bTaste) {
color = bColor;
taste = bTaste;
}
String getTaste() {
return taste;
}
String getColor() {
// Accessor method
return color;
}
}
TEST FILE:
import java.util.*;
public class Fruit1Test {
static Scanner console = new Scanner(System.in);
public static void main(String args[]){
Fruit1 a = new Fruit1("pinkish-red", "sweet-tart");
Fruit1 l = new Fruit1("yellow", "tart/sour");
a.taste();
a.color();
l.taste();
l.color();
System.out.println("Your apple is " + a.color + "in color and has a " + a.taste + " taste. ");
System.out.println("Your lemon is " + l.color + "in color and has a " + l.taste + " taste. ");
System.out.println();
}
}
a.taste(); will try to find method taste(); in your main file i.e. in Fruit1.java file. However as same is not found, it will throw error at compile time only that Method taste() is not found...
All below 4 statements will FAIL as those are not present...
a.taste();
a.color();
l.taste();
l.color();
As you are creating object of class by using below statement, already values to taste and color by use of constructor public Fruit1(String aColor, String aTaste){.
Fruit1 a = new Fruit1("pinkish-red", "sweet-tart");
I believe you now want to print the values of color and taste. To print those use getter methods that you have (getColor() & getTaste())
System.out.println("Your apple is " + a.getColor() + " in color and has a " + a.getTaste() + " taste. ");
System.out.println("Your Lemon is " + l.getColor() + " in color and has a " + l.getTaste() + " taste. ");
Note
You don't need to write public Fruit1(String bColor, String bTaste){ again as you have already defined above that....
Also your below statement should be before constructor and out of psvm
String color;
String taste;
Let me know if you are unclear...
Good Luck
You never declare the fields color or taste for the object Fruit1. Instead, you created the variables in the main method.
I suggest you read some basic tutorials on Java to get the hang of things. (Oracle also provides more advanced tutorials.)
I noticed in Fruit1, you are declaring the member variables in function main(). From the looks of it, Fruit1Test should have a main() fxn but Fruit1 should not. Take out those member variables out of main() and get rid of main() in Fruit1 (put it under the 'console' variable).
I also noticed that you have 2 constructors that both take in Strings. The compiler will probably complain about that too. I don't have a compiler in front of me but that's what I can tell just from looking.
For your first problem, it seems you're misunderstanding how to declare instance fields. You're creating them inside the main function, when you should create them directly inside the class.
For your second problem, see Fahim Parkar's comment, if it applies to your case. BTW it's a good practice to always have only one class/interface/enum per file, and have the file with the same name of the class (this second part may be mandatory in Java, I don't remember for sure - it applies to public classes, but I dunno if it also applies for "default, package protected" ones).
If they're named correctly, OTOH, maybe the error is because your "main" file didn't compile, so the "test" one didn't find it...
P.S. I just noticed you have two constructors with the same signature (number of parameters and same parameter types). You must remove one.

Array parameter passing

I'm in a beginner's java class. This Lab is for me to make a class "Wallet" that manipulates an array that represents a Wallet. Wallet contains the "contents[]" array to store integers represing paper currency. The variable "count" holds the number of banknotes in a wallet. After writing methods (that match provided method calls in a serpate Driver class) to initialize the Wallet and add currency/update "count", I need to transfer the array of one instantiated Wallet to another. I don't know how that would work because the one Wallet class has only been messing with a wallet called "myWallet" and now I need to take a new Wallet called "yourWallet" and fill it with "myWallet"'s array values.
//I should note that using the Java API library is not allowed in for this course
My Wallet class looks like this so far:
public class Wallet
{
// max possible # of banknotes in a wallet
private static final int MAX = 10;
private int contents[];
private int count; // count # of banknotes stored in contents[]
public Wallet()
{
contents = new int[MAX];
count = 0;
}
/** Adds a banknote to the end of a wallet. */
public void addBanknote(int banknoteType)
{
contents[count] = banknoteType;
count = count + 1;
}
/**
* Transfers the contents of one wallet to the end of another. Empties the donor wallet.
*/
public void transfer(Wallet donor)
{
//my code belongs here
}
...
The Driver code looks like this:
public class Driver
{
public static void main(String args[])
{
Wallet myWallet = new Wallet();
myWallet.addBanknote(5);
myWallet.addBanknote(50);
myWallet.addBanknote(10);
myWallet.addBanknote(5);
System.out.println("myWallet contains: " + myWallet.toString());
// transfer all the banknotes from myWallet to yourWallet
Wallet yourWallet = new Wallet();
yourWallet.addBanknote(1);
yourWallet.transfer(myWallet);
System.out.println("\nnow myWallet contains: "
+ myWallet.toString());
System.out.println("yourWallet contains: "
+ yourWallet.toString());
I want to use addBanknote() to help with this, but I don't know how to tell the transfer() method to transfer all of myWallet into yourWallet.
I had the idea to do somethign like this in transfer():
yourWallet.addBanknote(myWallet.contents[i]);
with a traversal to increase i for myWallet contents. It seems horribly wrong, but I'm at a complete loss as to write this method.
If my problem is so unclear that nobody can help, I would be more than happy to receive advice on how to ask a better question or on how to search with correct terms.
Thanks for any help you can provide.
I don't want to spoil your homework as you seem to be going the right way, but I do have some comments which you may either take or not :)
First, I would probably put the bank note types in some enumeration. But as that sounds a bit to advanced, consider
public class Wallet {
public static final int ONE_DOLLAR_BILL = 1;
public static final int FIVE_DOLLAR_BILL = 5;
...
// looks a bit more readable to me
myWallet.addBanknote(ONE_DOLLAR_BILL);
Transferring all the banknotes from the donor to yourself should not be so much of a problem
(a for loop would do) but I think you're in a world of hurt if you are trying to implement a
removeBanknote(int banknoteType);
as you are using count not only as a length but also as an index variable. By this I mean that you assume contents[0] ... contents[count-1] hold valid banknotes. And how do you remove one without too much work?
Warning: a bit more advanced
In your case I would probably opt to have a banknoteType of 0 indicating an empty banknote slot in your wallet, and implement _addBanknote(int banknoteType) as:
public void addBanknote(int banknoteType) {
for (int i=0; i < contents.length; i++) {
if (contents[i] == 0) {
contents[i] = banknoteType;
count++;
return; // OK inserted banknote at the first empty slot
}
}
throw new RuntimeException("Wallet is full");
}
This may be a bit overwhelming at this point. But it would allow you to implement:
public void removeBanknote(int banknoteType) {
for (int i=0; i < contents.length; i++) {
if (contents[i] == banknoteType) {
contents[i] = 0; // better: NO_BANKNOTE = 0
count--;
return;
}
}
throw new RuntimeException("This wallet does not contain a banknote of type " + banknoteType);
}
Please note that in both methods I return when I successfully removed or added the banknote. Only when I could not find a free slot, or the requested banknote, I finish the for loop and end up throwing an exception and thereby stopping the program.
I think the question is fine and I think you're on the right path. The way you're calling Wallet#addBanknote(int) is correct. What you have said is the right thing:
public void transfer(Wallet donor)
{
// Traverse the donor's wallet
// Add the bank note from the donor to this wallet
// What do you think also needs to happen to make sure
// the donor is actually giving their bank note?
}
Just another thing, what would happen in your Wallet#addBanknote(int) method if you have more contents than the MAX?
You can create either a constructor that takes another wallet, or a function (as already mentioned) and use System.arraycopy to copy the array in one fell swoop. System.arraycopy is fast, and its definitely overkill for something small like this, but its good tool to have in your toolkit.
The other alternative mentioned, copy the elements from one array to the other element by element in a loop will work fine too.
The myWallet inside the transfer method is named 'donor', and with that, it doesn't look horribly wrong:
addBanknote (donor.contents [i]);
You just need a loop around it, and to remove the yourWallet. which is the name of an instance of that class. That instance is inside the Class/method this, but needn't be specified, because there is no other addBanknote-Method in scope, which could be meant. (Thanks to mangoDrunk).

Categories