Related
Java I student here!
I am having a hard time understanding how to make set and get methods. I am working on a question in my textbook Java Programming, 9th Edition independently and I am asked to do the following:
"Create a class named Sandwich. Data fields include a String for the main ingredient (such as tuna), a String for bread type (such as wheat), ad a double for price (such as 4.99). Include methods to get and set values for each of these fields."
It then asks me to do this:
"Create an application named TestSandwich that instantiates one Sandwich object and demonstrates the use of the set and get methods."
So for the first part, I made a .java file with the following code:
public class Sandwich {
private String ingredient;
private String bread;
private double price;
public Sandwich(String ing, String bre, double pri) {
ingredient = ing;
bread = bre;
price = pri;
}
public void setIngredient(String ing) {
this.ingredient = ing;
}
public String getIngredient() {
return ingredient;
}
public String getBread() {
return bread;
}
public Double getPrice() {
return price;
}
}
For the second part, I did the following:
import java.util.Scanner;
public class TestSandwich {
public static void main(String[] args) {
String Ingredient;
String Bread;
Double Price;
Scanner keyboard = new Scanner(System.in);
System.out.println("MAKE A SANDWICH");
System.out.println("Enter an ingredient: ");
Ingredient = keyboard.nextLine();
System.out.println("Enter bread: ");
Bread = keyboard.nextLine();
System.out.println("Enter a price");
Price = keyboard.nextDouble();
Sandwich obj = new Sandwich(Ingredient, Bread, Price);
System.out.println("The ingredient is " + obj.getIngredient());
System.out.println("The bread is " + obj.getBread());
System.out.println("The price is " + obj.getPrice());
}
}
I completed this and it works well, however I realize that I did not create any set methods. Could someone explain to me a better way to do this according to the directions? I'm sure that this way works but I would like to do it by the book and be able to understand it better. I'm not sure where to start with creating the set methods. Please let me know. Thanks so much!
PS: This is NOT homework, I'm just trying to understand this a little better.
-Mark
Here you create an object with these values
Sandwich obj = new Sandwich(Ingredient, Bread, Price);
Here you create an empty object and then set the values
Sandwich obj = new Sandwich();
obj.setIngredient(Ingredient);
obj.setBread(Bread);
obj.setPrice(Price);
Consider this code in your class named Sandwich :
public Sandwich(String ing, String bre, double pri) {
ingredient = ing;
bread = bre;
price = pri;
}
This is called a constructor, a special kind of method that is having the same name as that of the class. But it does not return a value. This constructor is accepting three parameters, of which two are strings and one is a double value. In the constructor body you are actually setting values that are passed to the constructor as parameters and so you can consider this as a setter method which is setting three values at once.
Now consider this code inside the same class :
public void setIngredient(String ing) {
this.ingredient = ing;
}
This method is a setter method which sets only one value, i.e. ingredient. You can create other setter methods as well like this giving any name you want to. For example setBread and setPrice method inside the Sandwich class as follows:
public setBread(String bre) {
bread = bre;
}
public setPrice(double pri) {
price = pri;
}
You can either use the constructor to set the values or the "setter methods"(It is just a normal method that is used to accept and set the values). You can use a single method to set all the values in one go, which is what the constructor is doing or use individual methods to set each values like the setter methods we have defined.
If you are using a single method to set all values at once(in this case the constructor) then during the time of instantiating Sandwich class you need to pass all the values at once to the constructor like you did this :
Sandwich obj = new Sandwich(Ingredient, Bread, Price);
If you do not pass three variables to the constructor at once in the correct order, then compilation error will occur. As you already have a constructor setting three values, the other setter methods are not of great use except when you need to change the values afterwards. I hope this helps.
Simple go like:
System.out.println("Enter another price");
double newPrice = keyboard.nextDouble();
obj.setPrice(newPrice);
and print your obj before / after that call (and of course: #Overwrite toString() on that class to get meaningful output).
This question already has answers here:
Can someone explain a void return type in Java?
(5 answers)
Closed 6 years ago.
I'm confused about "void",
as it pertains to methods.
I don't know what the distinction between two methods is when one has "void" and another doesn't.
For example, if I do:
Public meth (int amount)
{
amount = initial * interest;
return amount;
}
( not sure if it was right, or even valid, to take the name "amount" and name it the same thing as my formal parameter, but what makes sense here is that you're performing a calculation and returning the result)
Then, if I did something like:
Public void Testing (int array[])
{
//code that would modify the internals of an array
}
Would the second one have no "return" because it's more of a general method, that can be applied to any integer array, while the first one is about doing work on specific variables?
Would also appreciate one or two more examples of when I would or wouldn't be using "void" and "return".
One other thing that seems to confuse me is calling methods.
I know sometimes I'll do something like, for example, using the Testing method above,
Testing(ArrayName);
Other times, it will be like:
NameOfWhateverImApplyingMethodTo.MethodName();
And then there are times when things will be done properly by:
Thing1.MethodName(Thing2);
Which circumstances would I switch the syntax for method calls like this?
Java is case sensitive, so the modifier Public is invalid, use public
You can't define a method as public methodName(int a), only a constructor has this signature, a method must be public void methodName(<signature>) for methods that don't return anything or public <return type> methodName(<signature>) for methods that do.
Void basically means that the method will not return anything.
If you did
String name= "tim";
public void getName(){
return name;
}
This would result in an error, because the getName method is returning a string object called name, but the method declaration is saying I am returning nothing - because it is void.
Instead the method should be :
String name = "tim";
public String getName(){
return name;
}
Now when the method getName() is called it will return a string object "name" with "tim" inside of it :)
You might have void for a set method. So for example
String name = "tim";
public void setName(String newName){
this.name = newName;
}
When this method is called you would use setName("Andy"); and it would set the value of the name variable to be "Andy". Nothing is returned in this method, because it is setting something, but there is no need to send anything back, so we use void on the method declaration.
Hope this helps.
The method that has void as return type does not return anything. For example you want to set a field firstName in your class. You will write a setting method like
public void setFirstName(String n) {
this.firstName = n;
}
As you can see you are just setting a class variable and does not require to return anything.
If you dont use void then you have to provide a return type for method. Like if you wish to write a getter for above variable as:
public String getFirstName() {
return this.firstName;
}
Once you provide a return type, you will have to return a value of that type otherwise your code will not compile.
Calling a method can be done based on where you are calling it from and what modifier is used:
If you are calling the method from the same class then you can simply write firstName = getFirstName()
If you are calling the method from another class then you require object of method's class as qualifier like personObject.getFirstName()
If you are calling a static method then you require class name as qualifier like Person.getFirstName();
Return type is what you get out of it. When you call it, what are you hoping to get back? For instance, if the method gets the average of two numbers, then you're expecting a number back, so the return type will be a number type, like "int" (integer).
You can see what it should be using that logic or by looking in the method for the word return - what comes after return is what is returned, and its type should be declared in the method (e.g. if it says "return 4;" it's returning an int, and should be e.g. public int getFour()
You also asked about e.g. testing() vs testing(word)
I remember having the same difficulty. The distinction between the two also relates to the method declaration line. I'll illustrate.
public String testing(){
return "a word";
}
Calling this method by doing "System.out.println(testing());" should print "a word". Calling this method by doing "System.out.println(testing("a word"));" will give you an issue - this is because when you call testing, it looks at the appropriate method: one in the right class, with the right return type and with the right arguments/parameters. If you're calling testing("a word"), that means you're using a String as an argument (because "a word" is a string), and so it tries to use the testing(String aString) method - which doesn't exist.
So you use empty brackets when the method takes no input, and you put stuff in brackets when the method expects stuff. This should be less confusing than it sounds, because it's usually logical - if you want to call a method that returns an average, you need to ask yourself "Average of what?" You'd probably need to supply it with the values you want the average of.
Moving on: (a) testing() versus(b) AClass.testing() versus(c) aclass.testing() -
In (a), there's no class specified. Therefore, if you call it from that class, Java can guess which class: this one, and it'll work. From any other class, it won't know what you're talking about, and might even insult you.
In (b), you're specifying a class in general - therefore it'll know what class to find it in - and it'll work if it's a "static method". *[see bottom]
In (c), you're specifying an instance of AClass you want to run "testing()" on*.
For instance, imagine you've created a class called Business. You make a hundred Business objects by specifying for each a name, number, address.
e.g.
Business b = new Business(name, number, address);
Then in the Business class you have a method "getName()". This method takes no argument - you could see that the brackets are empty - so if, from another class, you call "Business.getName()", how could it know which name you want? You've just made a hundred businesses!
It simply can't. Therefore, for such a method, you'd call "b.getName()" (b being the Business we created above) and it would get the name for this instance of a Business - namely, b.
I'm happy to help, so if you're confused about any particular parts of what I just wrote please let me know and I'll try to elaborate!
edit: A bit on static methods:
Static methods don't belong to an instance of the class. getName(), for example, would get the name of this Business - ie, this instance of the Business class. But let's say that in the Business class you made a method that took the first letter of each word in a String and transformed it to uppercase - like if you wanted to make the business names look more professional when you printed them out.
public static String stringToUpperCase(String aString){
aString = aString.substring(0, 1).toUpperCase() + aString.substring(1);
return aString;
}
And to use that, you change the getName() method from:
public String getName(){
return name;
}
to
public String getName(){
return stringToUpperCase(name);
}
The new method is used here to make the name have an uppercase first letter - but that is the extent of its involvement with the Business class. You notice it doesn't ask for information about the name, address, or number for a particular business. It just takes a string you give it, does something to it, and gives it back. It doesn't matter whether you have no Businesses or a hundred.
To call this method, you'd use:
System.out.println(Business.stringToUpperCase("hello"));
This would print Hello.
If it were not a static method, you'd have to make a new Business first:
Business b = new Business("aName", "aNumber", "anAddress");
System.out.println(b.stringToUpperCase("hello"));
And if the method did need access to more Business-instance information (like a business's name number or address) it wouldn't be able to be an instance variable.
The first example, a method without a return type at all, is a constructor; used when an instance is created with new. However, you can't return a value from a constructor. Something like,
this.amount = initial * interest; // return amount;
Sets the field amount to initial * interest.
Does this Java code involving a Book class use proper encapsulation? I feel it can be a lot simpler if I omit some methods but we're required to every method that is in there [especially setters and getters].
Here's the first class:
public class Book
{
private String title;
private double price;
private final double SALES_TAX=0.075;
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title=title;
}
public double getPrice()
{
return price;
}
public void setPrice(double price)
{
this.price=price;
}
public double getSalesTax()
{
return SALES_TAX;
}
public double increasePrice(double incresePrice)
{
return incresePrice;
}
public double calculateSales(double sales)
{
return sales;
}
}
And the second class:
public class BookDriver
{
public static void main(String[] args)
{
Scanner keyboard=new Scanner(System.in);
Book bookOne=new Book();
Book bookTwo=new Book();
bookOne.setTitle("Life of Pi");
System.out.print("Enter number to buy of "+bookOne.getTitle()+": ");
bookOne.setPrice(13.50*bookOne.calculateSales(keyboard.nextDouble()));
bookOne.setPrice((bookOne.getPrice()*bookOne.getSalesTax())+bookOne.getPrice());
System.out.print("Cost for "+bookOne.getTitle()+" $");
System.out.printf("%.2f"+"\n",bookOne.getPrice());
bookTwo.setTitle("Harry Potter: The Goblet Of Fire");
System.out.print("Enter number to buy of "+bookTwo.getTitle()+": ");
bookTwo.setPrice(22.00*bookTwo.calculateSales(keyboard.nextDouble()));
bookTwo.setPrice((bookTwo.getPrice()*bookTwo.getSalesTax())+bookTwo.getPrice());
System.out.print("Cost for "+bookTwo.getTitle()+" $");
System.out.printf("%.2f"+"\n",bookTwo.getPrice());
System.out.print("Enter percent increase of "+bookOne.getTitle()+": ");
bookOne.setPrice((bookOne.getPrice()*bookOne.increasePrice(keyboard.nextDouble()))+bookOne.getPrice());
System.out.printf("Cost of "+bookOne.getTitle()+": $"+"%.2f"+"\n",bookOne.getPrice());
System.out.print("Enter percent increase of "+bookTwo.getTitle()+": ");
bookTwo.setPrice((bookTwo.getPrice()*bookTwo.increasePrice(keyboard.nextDouble()))+bookTwo.getPrice());
System.out.printf("Cost of "+bookTwo.getTitle()+": $"+"%.2f"+"\n",bookTwo.getPrice());
keyboard.close();
}
}
I know that this is a lot so I'm not really expecting much in terms of a response but anything would help. Thanks!!
Let's look at the point of encapsulation. You have a Class which consists of properties and methods. The idea behind encapsulation is, you want the methods in your class to be the only way to change the value (state) of the properties. Think of it like this: if some other code in the program wants to change the value of one of the properties, it cannot do it itself, it must ask a method on the class they reside in to do it. That way, you control access to the properties.
The way this is implemented is with getter and setter methods of which you have created a few. A getter method returns the value of the property and a setter method changes it to a new value.
1.
Your getter and setter methods up to increasePrice() are good. You are preventing access to the properties other than from the methods on your class.
2.
increasePrice() only spits out what was passed into it. It doesn't change the value of any of the properties and thus has no purpose. If you want to be able to increase the price you can change the method like so:
public void increasePrice(double amountOfPriceIncrease) {
price += amountOfPriceIncrease;
/*
price += amountOfPriceIncrease is the same as
price = price + amountOfPriceIncrease
*/
}
3.
This line is a bit troubling. For starters, increasePrice() doesn't do anything other than spit out what was put into it and secondly, there is a lot going on in the one line that makes it complicated and hard to follow.
bookTwo.setPrice((bookTwo.getPrice()*bookTwo.increasePrice(keyboard.nextDouble()))+bookTwo.getPrice());
You dont necessarily need all the setters. For example, its probably reasonable to assume that a book has a title, and it doesnt change. So you can make it final, omit the setter, and pass it into the constructor.
Also, think about how you're modelling things. Is sales tax a property of a book? I'd say not.
Because all the required variables title, price for class Book are set to private, and that access can only be used using get..(), and changing it if possible can only be used using set..(some variable) or an instance method affecting one of the fields, it demonstrates proper encapsulation, so all getting and setting are regulated.
However, I spotted several mistakes in BookDriver, namely with the improper usage of Book fields.
The price should change only through setPrice or increasePrice.
You should also implement getPriceAfterTax to determine after-tax prices for a book.
The total cost of the books you bought should not involve any setPrice.
There is a mistake with public double calculateSales(double sales). It does nothing but returns back sales. The calculateSales should calculate the total cost of the book(s) being bought, using one int variable, and you also resorted in changing the price of these books, which shouldn't happen. It is the reason why you wrote messy code, as in the excerpt
bookTwo.setPrice(22.00*bookTwo.calculateSales(keyboard.nextDouble()));
bookTwo.setPrice((bookTwo.getPrice()*bookTwo.getSalesTax())+bookTwo.getPrice());
This avoids the potential case of changing the values of that BOOK object to unexpected or unusual values and value combinations.
Additionally, SALES_TAX can be made into a public static final double instead, as it is assumed to never change, and you can simply obtain SALE_TAX without requiring getSalesTax().
The last two methods do not make much sense. You simply return what you put in. Do it this way:
public double increasePrice(double increase)
{
price *= increase;
}
public double calculateSales(double sales)
{
//return {your formula}
}
I'm a beginner in Java programming, and I'm trying to make a voting machine program, where you can vote for Republicans or Democrats. My question is, how can I edit my method so I would be able to return two strings with two distinct values?
For example, look at my code all the way in the bottom. It's wrong, but I wanted the tester to be able to print out Democrats: (some number) and Republicans: (some number) in one method. How can I do that?
import java.lang.String;
public class VotingMachine1 {
private double Democrats;
private double Republicans;
public VotingMachine1() {
Democrats = 0;
Republicans = 0;
}
public void voteRepublican() {
Republicans = Republicans + 1;
}
public void voteDemocrat() {
Democrats = Democrats + 1;
}
public void clearMachineState() {
Republicans = 0;
Democrats = 0;
}
//this is where I'm having difficulties. I know its wrong
public double getTallies() {
System.out.println("Democrats: ", return Democrats);
System.out.println("Republicans: ", return Republicans);
}
}
No return is necessary there, since you aren't leaving a function. To do what you seem to want to do, just replace that last method with the following:
public void getTallies()
{
System.out.println("Democrats: " + Double.toString(Democrats));
System.out.println("Republicans: " + Double.toString(Republicans));
}
Also, since your votecounts should only ever be integers, there's no reason to declare them as doubles instead of ints.
What you are looking for here is a format string. A format string is used when you know what your output should look like, and only have a few "holes" where unknown data should be filled in. To output your data using format strings, you would use the System.out.format(String, Object...) method:
System.out.format("Democrats: %f\n", Democrats);
System.out.format("Republicans: %f\n", Republicans);
In this case, the %f indicates that a floating-point number (since your variables are declared as double) will be printed instead of the %f. However, you may wish to consider declaring them as int (or long) instead, in which case you would use %d instead of %f in the format strings.
Finally, you ought to change your getTallies() method to return void instead of double, as you are printing the values, not returning them.
Your code and your description are so contradictory, it is not clear that you even know what you are trying to do. I believe that this is the real root of your problems.
Here goes:
public double getTallies()
{
System.out.println("Democrats: ", return Democrats);
System.out.println("Republicans: ", return Republicans);
}
First, your question says that you want to "return two strings with two values" ... but you have declared the method as returning one double.
Next, your code is printing values ... not returning them.
You've also made some major mistakes at the syntactic level, largely (I believe) because you are trying to do contradictory things:
return Republicans is not a valid Java expression, so you can't use it as a argument to the println method.
The println method can't be called with two arguments, as your code is trying to do. There is a zero argument version and a number of one argument overloads ... but no overloads with two or more arguments.
Basically, you need to start by making up your mind about what this method is supposed to do. Is it supposed to:
return the tallies (as two doubles)?
return a string representing the two tallies?
return nothing ... and output the two tallies to standard output?
do something else?
Once you've made up your mind:
code the method to do what you've decided it should do, and
chose a method name that correctly reflects what it is supposed to do. Hint: a method that starts with get is conventionally a "getter" that returns the attribute or attributes themselves ... not a String rendering.
double is a bad choice of type for a vote count too:
You cannot have a fractional vote.
You want to represent vote counts precisely and floating point types (like double) are not precise. (Or at least, not in the sense that you require.)
When you attempt to format or output a double, the resulting character string is likely to include a pesky decimal point ... or worse.
You should use int or long instead of double.
Finally, this is a serious Java style violation, and should get you a significant penalty if your marker is paying attention.
private double Democrats;
private double Republicans;
Variable names in Java should start with a LOWER CASE letter.
A few more random comments:
import java.lang.String; is superfluous as all classes in package java.lang are automatically imported in every Java source file.
Votes can not be fractional. People can't vote 0.75 candidate A, and 0.25 candidate B. If you use integer datatypes (int or long), you will be reflecting this fact better. Also, you will be saving yourself a lot of headache when you start obtaining results like 379857.999999. This is because floating point types have a better range, but worse precision (especially noticeable when working with pure integers).
According to Java usual naming conventions, variable names should start with a lowecase letter.
A better name for function getTallies is printTallies.
For output purposes, it's much better to use string formatting than concatenation. Some advantages are: multiple formats supported, ease of use, and internationalization.
Putting all together:
private int democratVotes;
private int republicanVotes;
public void printTallies() {
System.out.format("Democrats: %,d%n",democratVotes);
System.out.format("Republicans: %,d%n",republicanVotes);
}
In this particular case, votes will be printed with thousand separation (ex: 3,345,623 instead of 3345623). Check Java's Formatting Numeric Print Output tutorial.
Thinking better about it, there are some alternatives where getTallies would effectively be returning some form of value:
1) Make it to return a String with both tallies. It would be hard and inefficient to separate the tallies later, though.
public String getTallies() {
return "Democrats: %,d votes. Republicans: %,d votes.%n".format(democratVotes,republicanVotes);
}
2) Make it to return an array.
public int[] getTallies() {
return new int[2]{ democratVotes, republicanVotes };
}
public int[] getTallies1() { // Same as getTallies, but written step by step.
int[] result= new int[2] ;
result[0]= democratVotes ;
result[1]= republicanVotes ;
return result ;
}
3) Make it to return a class.
public VotingMachineResults getTallies() {
return VotingMachineResults(democratVotes,republicanVotes) ;
}
public static class VotingMachineResults {
private int democratVotes;
private int republicanVotes;
public VotingMachineResults(democratVotes,republicanVotes) {
this.democratVotes= democratVotes ; // `this` required to disambiguate field democratVotes from parameter democratVotes.
this.republicanVotes= republicanVotes ;
}
public int getDemocratVotes() {
return democratVotes ;
}
public int getRepublicanVotes() {
return republicanVotes ;
}
}
As you can see, this class is very similar to VotingMachine1, but it does not accept internal state changes. It is a "value" class.
In Java, you concatenate Strings with the + operator. Proper syntax for what you were trying to do looks like this:
System.out.println("Democrats: " + Democrats);
System.out.println("Republicans: " + Republicans);
A return statement is only used when you want to return some object or value to a method that called your current method. It is not appropriate in this place since you're only passing a value to another method (println()).
ALSO, you need to fix your getTallies() method. Make it return void instead of double since you aren't returning anything.
Here's something completely different: why not override toString()?
Presumably, any instance of VotingMachine1 will apply for all votes that you care about for that instance. That is to say, you don't create a new instance of a VotingMachine1 every time someone casts a vote.
So, what you can do is override the toString() method. We'll also use String.format() to handle the numerical values.
#Override
public String toString() {
// assumes that Democrats and Republicans are declared as int
// since it's pointless to indicate percentages of a vote
return String.format("Democrats: %d\nRepublicans: %d", Democrats, Republicans);
}
Now, whenever you vote, you can use the toString() method to get the information (which is called whenever one does System.out.println(object).
VotingMachine1 voter = new VotingMachine1();
voter.voteDemocrat();
voter.voteRepublican();
System.out.println(voter);
/* This prints:
Democrats: 1
Republicans: 1
*/
A less specific answer to your question would be to return an Object called (say) Votes
public class Vote {
int democratVotes
int republicanVotes
}
and then make your VotingMachine class simply return an instance of this object (suitably changed to make it immutable).
On my project we have created a generic version of this called a Tuple that returns a pair of values in a single object - it has an overloaded toString method for easy printing.
you can return an array with [0] and [1] as key and devide it on the basis of your need..
like
returnArray[0]="first string";
returnArray[1]="second string";
and use it ur way...
I have a class that stores a number in the millions. What I would like to do is override the method to get that number and apply a string formatter for readable UIX output.
This is what I have to "overload" the to gets:
class dudViewModel {
public int gettotal () {
return this.total;
}
public String gettotal(String formated) {
return String.format("%.1f", (float)total / 1000000);
}
}
So it's the difference between the two following calls:
gettotal(); // returns 23,400,000
and
gettotal("formatted"); // returns 23.4
Is there a better way or pattern in java to overload an individual method() that returns a number and override i with a tostring() call somehow to overide default number return and instead return a formatted string?
I think the best way is to separate the presentation from the business logic. In this approach, you'd just have a single getTotal() method returning int. A completely separate method of a separate class would take that int and format it for the UI.
or patter in java to overload an individual method() that returns a number and override i with a tostring()
You can apply Decorator pattern which allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class
What a method does, must be indicated in its name. In this case, the two methods should be named different rather than trying to overload, overloading should alter the processing, not the total effect or output.
class dud {
public int getTotal () {return this.total;}
public String getFormattedTotal() {return String.format("%.1f", (float)total / 1000000);}
public String getFormattedTotal(String customFormat) {return String.format(customFormat, (float)total / 1000000);}
}
Separate the data from its representation and you can also test it in isolation.
class Dud {
public int getTotal () {return this.total;}
}
class DudPresentation {
private Dud dud;
public DudPresentation(Dud dud){
this.dud = dud;
}
public String getTotal() {
return getTotal("%.1f");
}
public String getTotal(String format) {
int total = dud.getTotal();
return String.format(format, (float)total / 1000000);
}
}