File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Beginning Java and the fly likes Classes, Classes, and More Classes Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "Classes, Classes, and More Classes" Watch "Classes, Classes, and More Classes" New topic
Author

Classes, Classes, and More Classes

Laura Peterson
Greenhorn

Joined: Mar 14, 2013
Posts: 23

So I'm still having trouble with classes. I'm working on a new problem, which goes something like this:

Write a class named GroceryList that represents a person's list of items to buy from the market, and another class named GroceryItemOrder that represents a request to purchase a particular item in a given quantity (example: 4 boxes of cookies).
The GroceryList class should use an array field to store the grocery items, as well as keeping track of its size (number of items in the list so far). Assume that a grocery list will have no more than 10 items. A
GroceryList object should have the following methods:

public GroceryList() - Constructs a new empty grocery list.
public void add(GroceryItemOrder item) - Adds the given item order to this list, if the list is not full (has fewer than 10 items).
public double getTotalCost() - Returns the total sum cost of all grocery item orders in this list.

The GroceryItemOrder class should store an item quantity and price per unit. A GroceryItemOrder object should have the following methods:

public GroceryItemOrder(String name, int quantity, double pricePerUnit) - Constructs an item order to purchase the item with the given name, in the given quantity, which costs the given price per unit.
public double getCost() - Returns the total cost of this item in its given quantity. For example, 4 boxes of cookies that are 2.30 per unit have a cost of 9.20.
public void setQuantity(int quantity) - Sets this grocery item's quantity to be the given value.

I'm pretty sure I have the GroceryItemOrder class done correctly, and I have my test/main method class done... It's the GroceryList that I seem to have trouble working with the array and using it in conjunction with the other class. Here's what I have:

GroceryList Class:


GroceryItemOrder Class:


Main Method/Test Class:


Any assistance would be appreciated, and thank you!

Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39794
    
  28
Start designing centrifugally, ie from the centre out, and start coding centripetally, ie from the periphery towards the centre. So write your item class first and get it working. I would suggest the one additional thing you need in your Item class is a toString method, which when called might return
4 packets of cookies @$2.30 cost $9.20
Then write an item tesing class, which will look similar to what you have already. But you only test the item class/objects here. Leave out the grocery class for the time being. You will write this sort of thing:-I think that as long as no awkward so‑and‑so tries to change the quantity of your apples to a ridiculous amount, it will work all right. In fact, I have only looked at the item class, but it looks good so far

You realise that the this. and the () after return in the getCost method are redundant; you can remove them and not notice any difference. The this. in the constructor and set method are necessary.
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4999
    
    8

1. As a matter of convention, method-level comments are placed before the method, not after.

2. It's redundant to initialize the member variable list to null; Java does that implicitly. Also, you have only one constructor and it initializes the array, so any assignment you make at the declaration on line 5 will be superceded in line 10.

3. Avoid the name list. There is a standard List type (java.util.List) and there is also distinct difference between a list and an array as general data structures, although lists can be implemented using arrays. Giving an array the name list can be confusing to readers who are familiar with the List type and the list data structure. OTOH, you could argue that there is the ArrayList. I would argue back, "Exactly. You don't have to add to that confusion."

4. Try something more expressive like groceryItems, for example.

5. What is the num variable used for? I don't see it ever referenced, outside of the constructor. Again, assigning 0 to num in the constructor is redundant because by default, all numeric member variables are initialized to 0 when an object is instantiated, if they are not explicitly initialized. Some will say it's a matter of preference, some will say it makes the intent explicit. I'm lazy and I expect people who read my code to know at least that much about how Java works so I leave the default initialization to Java whenever I can.

6. Going back to your non-use of num, the termination expression of the for-loop on line 25 references the length of the array. Does it make sense to use something else here?

7. In your main(), I don't see any benefit to declaring a variable for each item you add to the grocery list. This is just as readable, IMO:

8. In this case, the name list is actually Ok. I know, it can be confusing. The reason I say it's Ok here is because it's a local variable and it's easy to see its declared type. Otherwise, when the scope is wider than a method, it's more likely to get confused as something that might refer to an object of type java.util.List


Junilu - [How to Ask Questions] [How to Answer Questions]
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4999
    
    8

And if you were to use num, remember what your requirements say: you should track the number of items in the grocery list. Where would you track that number? Right now, you're not.
Larry Frissell
Ranch Hand

Joined: May 16, 2008
Posts: 82
    
    2


The method above would give you a compile error since "list" is a simple array of GroceryItemOrder. Your add method needs to be corrected, to put the item into GroceryItemOrder[num] and increment num .
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4999
    
    8

Larry Frissell wrote:The method above would give you a compile error since "list" is a simple array of GroceryItemOrder

See what I mean when I say that the name list can create confusion? The java.util.List interface has an add() method. That's a sneaky bug hiding behind an ambiguous name.

@Larry -- I had hoped that the OP would use my advice about the ambiguous name to find that bug. I'll give you the benefit of the doubt on this and chalk it up to an unintentional spoiler post. Cheers
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4999
    
    8

This may seem a little advance for beginners but I have found that method chaining is a great technique for writing more expressive code. Take this for example:

The beauty of this technique is that some of the calls can be switched, so you don't have to remember the exact order and the code becomes very semantic:

Sure, it's more verbose but I would buy expressive with some verbose any time. I'll leave it as an exercise for you to figure out how to write code that allows you to do this.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 8196
    
  23

Junilu Lacar wrote:This may seem a little advance for beginners but I have found that method chaining is a great technique for writing more expressive code.

I'm also a fan of fluent interfaces, but I'd suggest that in this case you don't want to confuse the list with the items you add to it, so I'd probably do something more like:but there are many alternatives.

@Laura: The fluent interface technique is also often used with builder classes, so you might want to Google "Builder pattern".

Winston

Isn't it funny how there's always time and money enough to do it WRONG?
Articles by Winston can be found here
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4999
    
    8

In the examples I gave, some() is a factory method that instantiates a named GroceryItemOrder and both each() and count() would be methods of GroceryItemOrder that returned a reference to this. The type of the expression in the add() method can be inferred. Once you get used to the style and the inferences, prepending the class name becomes somewhat redundant. Admittedly, it does help people figure it out at first glance. Some refactoring discussion might lead you to rename some() to item() so that the code reads:


Winston Gutkowski wrote:but there are many altenatives

Agreed. Of course, I still prefer the way I did it
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 8196
    
  23

Junilu Lacar wrote:Of course, I still prefer the way I did it

And how about:
Item.named("apples").count(5).each(0.40).addTo(myList);
would that be a "passive" interface?

@Laura - This is just one of the drawbacks of fluent interfaces: There are many ways to implement them, so you have to be very careful to be consistent and document them well. The best can be very nice to use; but bad ones can be awful.

Winston
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4999
    
    8

Winston Gutkowski wrote:And how about:
Item.named("apples").count(5).each(0.40).addTo(myList);

The thing about this one is that it increases coupling. Now Item knows about a specific type of object that collects it whereas before there was only the collection type naturally knowing about the type of object it holds. Plus, this doesn't read as naturally as the other way.

"Hey, Item class, make one of yourself named 'apples' that has a count of 5 and a price of 0.40, then have it add itself to myList"

vs.

"Hey, myList, add this item named 'apples' that has a count of 5 and a price of 0.40."
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 8196
    
  23

Junilu Lacar wrote:The thing about this one is that it increases coupling. Now Item knows about a specific type of object that collects it whereas before there was only the collection type naturally knowing about the type of object it holds. Plus, this doesn't read as naturally as the other way.
"Hey, Item class, make one of yourself named 'apples' that has a count of 5 and a price of 0.40, then have it add itself to myList"

Agreed. However, I'd say that in this case the whole business of an "Item" is absolutely linked to the List that it's part of. In application terms, I'd call it a "line item" and, if I were designing it, it would be based on a Product (or simply a type). Basically, it's a "bunch of" object.

Probably too many nights spent on BOS and Inventory systems...

Winston
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4999
    
    8

Winston Gutkowski wrote:
@Laura - This is just one of the drawbacks of fluent interfaces: There are many ways to implement them, so you have to be very careful to be consistent and document them well. The best can be very nice to use; but bad ones can be awful.

This is true about any type of API, not just fluent interfaces. The best ones (APIs) are self-documenting, expressive, intuitive, and align with the natural language used to discuss the problem space. That's why good names are very important; you have to choose them carefully so as not to create confusion, ambiguity, or misdirection. A good example (of a poor name choice) from this thread was using the name "list" for an array.

I often tell my colleagues this: "Write code that other developers can easily read. The computer simply does exactly what you tell it to do, whether it's the right thing or not. It's your job to write clear, expressive code so that you and others can be certain that you are telling the computer precisely what you want it to do. Most often, bugs are caused by a difference between what you actually told the computer to do and what you meant to tell it."
Laura Peterson
Greenhorn

Joined: Mar 14, 2013
Posts: 23

Thanks to everyone- I did manage it. Thanks for all the helpful hints and pointers about general use, too!
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39794
    
  28
You’re welcome
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Classes, Classes, and More Classes