Start learning free

LESSON 557 OF 569 · OBJECT-ORIENTED PROGRAMMING - CHALLENGES

Inventory Item in Java: Private Stock, Checked Methods

Practice O(1) Read the full explanation

A shop keeps track of how many pieces of each item it has: the item's stock. The stock can never go below 0, and it changes only when pieces are sold or new ones arrive. So the stock is a private field, changed only through two methods that check the rules. The item's name has no rules to protect, so it stays a field any code can read.

Implement the class InventoryItem:

  • InventoryItem(name, stock) creates an item with that name and that many pieces in stock. The name is kept in a field name that other code can read.
  • sell(n) sells n pieces. If n is at least 1 and at most the stock, it lowers the stock by n and returns true. Otherwise it changes nothing and returns false: selling 0 pieces, a negative number of pieces, or more pieces than there are in stock is refused.
  • restock(n) adds n pieces to the stock when n is at least 1, and ignores n otherwise. It returns nothing.
  • getStock() returns the stock. It is the only way for other code to read it.

Keep the stock private the way the Access Modifiers lesson does in your language: self._stock in Python (private by convention), a #stock field in JavaScript, and the private keyword in Java, C++, C#, TypeScript, Kotlin, Scala and Swift. In Kotlin and Scala the constructor's second parameter is named initialStock, and the private stock starts at its value.

Each test case creates one item, then applies a list of operations to it, in order. The output has one line per test case: the item's name and a colon, then what each sell and getStock call returns, separated by spaces, with sell's answer printed as True or False. The starter code spells these names the way your language does: get_stock in Python, Sell, Restock and GetStock in C#.

 

Example 1:

Input:
    InventoryItem("Pencil", 5)
    sell(3)
    getStock()
    sell(5)
    getStock()
    restock(10)
    getStock()
Output: Pencil: True 2 False 2 12
Explanation: Selling 3 of the 5 pencils works and leaves 2. Selling 5 more is refused, because only 2 are left,
and the stock stays 2. restock(10) brings it to 12.

Example 2:

Input:
    InventoryItem("Mug", 4)
    sell(4)
    getStock()
    sell(1)
    getStock()
Output: Mug: True 0 False 0
Explanation: Selling all 4 mugs is allowed and leaves 0. With nothing left, even one mug can't be sold.

Example 3:

Input:
    InventoryItem("Lamp", 2)
    sell(0)
    sell(-3)
    restock(0)
    restock(-5)
    getStock()
    restock(1)
    sell(3)
    getStock()
Output: Lamp: False False 2 True 0
Explanation: Selling 0 or -3 lamps is refused, and restocking 0 or -5 lamps is ignored, so the stock is still 2.
After restock(1) there are 3 lamps, and selling all 3 works.

 

Constraints:

  • A name is one word of English letters. 0 <= stock <= 104 when the item is created.
  • -104 <= n <= 104 in every sell and restock.
  • A test case has from 1 to 1000 operations, and at least one of them is a sell or a getStock.
STEP 1 OF 7
    Ctrl + Enter to check

    JAVA · OBJECT-ORIENTED PROGRAMMING - CHALLENGES

    Inventory Item in Java, explained

    Problem overview

    A shop tracks how many pieces of each item it has. The stock can never go below 0, and it changes only when pieces are sold or new ones arrive. So InventoryItem keeps the stock in a private field and changes it only through two methods that check the rules. The item's name has no rules to protect, so it is a public field.

    • InventoryItem(name, stock) creates an item with that name and that many pieces.
    • sell(n) sells n pieces if n is at least 1 and at most the stock, lowering the stock and returning true. Otherwise it changes nothing and returns false.
    • restock(n) adds n pieces when n is at least 1 and ignores n otherwise. It returns nothing.
    • getStock() returns the stock, the only way for other code to read it.

    For an item with a stock of 5, sell(3) returns true and leaves 2. Then sell(5) returns false because only 2 are left, and the stock stays 2. restock(10) brings it to 12.

    Approach: check first, then change

    Both methods follow the same pattern. First look at the request, and refuse it if it breaks a rule. Only then change the stock. For sell, a request is refused when n is below 1 (zero or negative pieces are not a sale) or above the stock (you can't sell what you don't have). Selling exactly the whole stock is fine and leaves 0. Because the check comes before any change, a refused sale leaves the stock as it was, and no code path can push the stock below 0.

    Making stock private is what gives these checks their force. Outside the class, the only way to change the stock is through sell and restock, so every change is checked.

    Step by step

    1. Declare public String name. Other code may read it directly.
    2. Declare private int stock. Outside the class, item.stock is a compile error.
    3. Store both parameters in the fields with this.name and this.stock.
    4. In sell, refuse bad requests first: if (n < 1 || n > stock) returns false. The two conditions are joined with ||, "or".
    5. Complete the sale: after the if, subtract n from stock and return true. Only a request that passed the check reaches this line.
    6. In restock, add only for a real delivery: if n >= 1, add n to stock. Zero or a negative number is ignored.
    7. getStock returns stock.

    The solution in Java

    class InventoryItem {
        public String name;
        private int stock;
        public InventoryItem(String name, int stock) {
            this.name = name;
            this.stock = stock;
        }
        public boolean sell(int n) {
            if (n < 1 || n > stock) {
                return false;
            }
            stock -= n;
            return true;
        }
        public void restock(int n) {
            if (n >= 1) {
                stock += n;
            }
        }
        public int getStock() {
            return stock;
        }
    }
    

    Details worth noting:

    • Inside sell, stock is the field and n is the parameter. There is no name clash, so this. isn't needed there.
    • The method returns early with return false, so the lines below the if run only for a valid sale.
    • The return type of restock is void: it reports nothing, even when it ignores the request.
    • In the tests, sell's answer is printed as True or False. That is the tests' output format; Java prints true and false.

    Using the class

    InventoryItem it = new InventoryItem("Pencil", 5);
    System.out.println(it.sell(3));
    System.out.println(it.getStock());
    System.out.println(it.sell(5));
    System.out.println(it.getStock());
    it.restock(10);
    System.out.println(it.getStock());
    System.out.println(it.name);
    InventoryItem l = new InventoryItem("Lamp", 2);
    System.out.println(l.sell(0) + " " + l.sell(-3));
    l.restock(0);
    l.restock(-5);
    System.out.println(l.getStock());
    l.restock(1);
    System.out.println(l.sell(3) + " " + l.getStock());
    

    prints:

    true
    2
    false
    2
    12
    Pencil
    false false
    2
    true 0
    

    The lamp case shows every rule: selling 0 or -3 is refused, restocking 0 or -5 is ignored, so the stock is still 2. After restock(1) there are 3 lamps, and selling all 3 works and leaves 0.

    What the compiler does with private

    From another class, item.stock is rejected at compile time with error: stock has private access in InventoryItem, whether you try to read it or to assign it. Reading goes through getStock(), and the only ways to change the number are sell and restock. The name is different: item.name is public, so other code can read it, and also change it, because no rule protects it.

    Each item has its own stock. Selling pencils from one InventoryItem never changes the stock of another object, even one with the same name.

    Edge cases and common mistakes

    • Selling exactly the stock. Use n > stock for the refusal, not n >= stock, or the shop could never sell its last pieces.
    • Forgetting the lower bound. Without n < 1, sell(-3) would pass the check and raise the stock by 3 while returning true.
    • Using && where || belongs. No number is both below 1 and above the stock, so that condition would never refuse anything.
    • Changing the stock before checking. The check must come first, or a refused sale would still modify the stock.
    • Making stock public. Code outside could then write item.stock = -5 and break the rule the class exists to protect.
    • Accepting a negative restock. restock(-5) would quietly act as a sale without any of its checks.

    Complexity

    Each method does a couple of comparisons and at most one arithmetic update, so all four are O(1) in time. The object stores a name and one integer.

    Keep going with Java500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free