I have a Class named Item.
public class Item {
private int code;
private String name;
private double price;
private int quantity;
public Item(int code, String name, double price, int quantity) {
setCode(code);
setName(name);
setPrice(price);
setQuantity(quantity);
}
//Item getters and setters
And I have a Class named Stock that creates an ArrayList of Items.
public class Stock {
private ArrayList<Item> stock;
public Stock() {
stock = new ArrayList<Item>();
}
public ArrayList<Item> getStock() {
return stock;
}
I also have a Class named ItemRegister that adds an Item to the Stock.
public class ItemRegister extends Stock {
public void registerItem(String name, double price) {
getStock().add(new Item(setItemCode(), name, price, 0));
}
private int setItemCode() {
return getStock().size() + 1;
}
I'm using unit tests to see if I did add an Item to the Stock.
public class ItemRegisterTest {
#Test
public void testIfHasRegisteredItemInStock() {
Stock s = new Stock();
assertTrue(s.getStock().size() == 0);
ItemRegister i = new ItemRegister();
i.registerItem("Oleo", 20.0);
assertTrue(s.getStock().size() == 1);
}
}
When I run these tests it is returning an error.
On the second assertTrue, if I test with the object i it'll return true but what I want is to add to Stock and not ItemRegister because if later on I wanna consult Stock I'll call Stock and not ItemRegister.
From the comments, what you can do is maybe changing the parent-child relationship and having the ItemRegister holding an instance of a Stock object. So, you can modify the ItemRegister class like this:
public class ItemRegister {
Stock s;
public ItemRegister(Stock s) {
this.s = s;
}
public void registerItem(String name, double price) {
s.getStock().add(new Item(setItemCode(), name, price, 0));
}
private int setItemCode() {
return s.getStock().size() + 1;
}
}
Then, the test code you originally wrote will be true with a slight modification ItemRegister i = new ItemRegister(s);, and you can work on one instance of Stock object.
I want is to add to Stock and not ItemRegister because if later on I wanna consult Stock I'll call Stock and not ItemRegister.
Then you need to wrap Stock into ItemRegister.
public class ItemRegister {
Stock stock;
public ItemRegister(Stock stock) {
this.stock = stock;
}
public void registerItem(String name, double price) {
stock.getStock().add(new Item(setItemCode(), name, price, 0));
}
private int setItemCode() {
return stock.getStock().size() + 1;
}
}
Use it in your unit tests like this:
public class ItemRegisterTest {
#Test
public void testIfHasRegisteredItemInStock() {
Stock s = new Stock();
assertTrue(s.getStock().size() == 0);
ItemRegister i = new ItemRegister(s);
i.registerItem("Oleo", 20.0);
assertTrue(s.getStock().size() == 1);
}
}
Related
I was creating a Java program for my OOP class. The program is supposed to be the start of a store interface and we are going to build off it during the rest of the semester. Whenever I was to add a new product and try to access how much of it is in stock my program says the "Id DNE -1" which is only supposed to print when an id is called and it doesn't exist. I'm not too sure why it's not recognizing the product I just put in. Below are all my classes that are used. I think the error has to be somewhere in my inventory class but I'm not too sure. Any tips or tricks for OOP would greatly be appreciated as well. Cheers
public class main
{
public static void main(String[] args)
{
StoreManager r3 = new StoreManager();
Inventory r4 = new Inventory();
r4.addNewProduct(1,"apple",1.50,50);
System.out.println(r3.qCheck(1));
}
}
public class StoreManager
{
private Inventory store1 = new Inventory();
private Product store2 = new Product();
static Inventory r4 = new Inventory();
public StoreManager(){}
public int qCheck(int id)
{
if (store1.getStock(id) < 0)
{
System.out.println("Id DNE");
return -1;
} else
{
return store1.getStock(id);
}
}
public double dqcheck(int id, int desiredQuantity) {
if (store1.getStock(id) >= desiredQuantity) {
store1.removeStock(id, desiredQuantity);
double cost = store2.getPrice() * desiredQuantity;
return cost;
}
else {
System.out.println("id DNE");
}
return -1;
}
}
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Inventory
{
//Var Declarations
private int quantity;
// FIXME: 2021-02-07 idk if im usin type right
private Product type;
//Hashmap for the data structure in this class using the Product is gonna be a key
// the value is the Integer for the quantity
private Map<Product,Integer> invt = new HashMap<>();
//blank constructor
public Inventory()
{
}
// FIXME: 2021-02-05 Getter and setter methods not really in use
public int getQuantity(){return quantity;}
public Product getType(){return type;}
/*
Used to initialize a new product and its stock into our Hashmap
the Quantity is the Value of our hashmap while we are using the
Product as a whole to be the key
no return type
*/
public void addNewProduct(int id,String name, double price, int quantity)
{
Product product = new Product(name, id, price);
invt.put(product,quantity);
}
/*
Used to get the get for a given id
compares the Id to one of the ids in the Key values to find the product
returns an int for the amount in stock or a -1 as an error if the id doesn't exist
*/
public int getStock(int id)
{
Set<Product> set = invt.keySet(); // Conversion of keys into sets
Iterator<Product> it = set.iterator(); // the only way i could get the code to interate throughout the keys
while (it.hasNext())//Only way i could go through the code
{
type = it.next();// FIXME: 2021-02-07 Idk if type is being used right here but i needed a buffer variable for it to work
Product a = it.next();
if (a.getId() == id)
{
return invt.get(type);//type is an object of Product here so we can use it as a key
}
}
return -1;//representation of error ID Dne
}
/*
Used to add a given Stock for a given Id
void doesnt return anything
assuming inpputed id exists if Dne doesnt do anythin or return an error
*/
public void addStock(int id, int amountToAdd)
{
//Possibly make this hashmap id check into another private method and call
Set<Product> set = invt.keySet();
Iterator<Product> it = set.iterator();
while (it.hasNext())
{
type = it.next();
if (type.getId() == id)
{
invt.put(type, invt.get(type)+amountToAdd);
return;//exit the function after the addtion is done
}
}
}
/*
Used to remove a given amount of product from stock in reference to a given Id
void doesnt return anythin
assuming id exits otherwise it does nothin
*/
public void removeStock(int id, int amountToRemove)
{
Set<Product> set = invt.keySet();
Iterator<Product> it = set.iterator();
while (it.hasNext())
{
type = it.next();
if (type.getId() == id && invt.get(type) - amountToRemove >= 0)//checks if the id exits and if there whould be enough stock to remove
{
invt.put(type, invt.get(type)-amountToRemove);
return;
}
}
}
/*
Prints all product information in reference to the id
*/
public void getInfo(int id)
{
Set<Product> set = invt.keySet();
Iterator<Product> it = set.iterator();
while (it.hasNext())
{
type = it.next();
if (type.getId() == id)
{
System.out.println("Name: "+type.getName());
System.out.println("Id: "+type.getId());
System.out.println("Price: "+type.getPrice());
System.out.println("Quantity: "+ invt.get(type)); // FIXME: 2021-02-07 Idk if Quanitity and Id are needed here
}
}
}
}
public class Product
{
private String name;
private int Id;
private double price;
public Product(String Name, int Id,double Price)
{
this.name = Name;
this.Id = Id;
this.price = Price;
}
public Product()
{
}
//Getter Methods
public String getName() {return name;}
public int getId() {return Id;}
public double getPrice() {return price;}
}
public class main
{
public static void main(String[] args)
{
StoreManager r3 = new StoreManager();
r3.store1.addNewProduct(1,"apple",1.50,50);
System.out.println(r3.qCheck(1));
}
}
Use the Inventory object that belongs to StoreManager, that's the only one it can access.
It's a code about a 'shopping cart' that can hold items of a class called 'item'. I had to complete the class 'item' and write another class 'discount' that can reduces the price of an item.
import java.util.ArrayList;
public class Shoppingcart extends Item {
// all shopping carts:
private ArrayList<Shoppingcart> allshoppingcart = new ArrayList<Shoppingcart>();
//Items in the shopping cart:
private ArrayList<Item> content = new ArrayList<Item>();
// Counter for shopping carts
private static int number;
/**
* Constructor
*/
public Shoppingcart() {
allshoppingcart .add(this);
this.number = number ;
this.number++;
}
/**
* load something in Shoppingcart
*/
public void load(Item i) {
this.content.add(i);
}
/**
* Sum of all items loaded in the shoppingcart
*
* #return sum of the content in the shopping cart
*/
public double sumShoppingCart() {
double sum = 0.0;
for (Item i : content) {
sum = sum + item.getPrice();
}
return sum;
}
}
The class 'item' so I can store two different types in the arraylist.
public class Item {
// normal price of item
protected double price;
// Name of product
protected String name;
/**
* setter for price and name
*/
public void setPB(String name, double price) {
this.name = name;
this.price = price;
}
/**
* getter for price
*/
public double getPrice() {
return this.price;
}
/**
* getter for the name
*/
public String getName() {
return this.name;
}
}
The class 'discount' to reduce an item for an example like a sale (special-offer).
public class Discount extends Item
{
// instance variables - replace the example below with your own
public Discount()
{
// initialise instance variables
}
public void makeSale(int percent){
percent =(100-percent)/100;
price = w.getPrice()*percent;
}
}
A test class
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList<Item> content = new ArrayList<>();
Item item = new Item();
Item item1 = new Item();
Item item2 = new Item();
item.setPB("Steak", 100.00);
item1.setPB("Water", 200.00);
item2.setPB("Groceries", 300.00);
content.add(item);
content.add(item1);
content.add(item2);
System.out.println("The item has the value : " + item.getPrice() + " and the name: " + item.getName());
System.out.println("There are : " + content.size() + " Item(s) in the shopping cart.");
}
}
How do I access an item and reduce it for a sale?
Thank you
This is a typical OOP exercise. You want to access two different types in a single collection. To do so they both need to have the same interface or parent.
If you use an Abstract base class you can use the following example.
First lets make an abstract Item class:
abstract class Item {
protected double price;
protected String name;
public Item(double price, String name) {
this.price = price;
this.name = name;
}
public double getPrice() {
return this.price;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setPrice(double price) {
this.price = price;
}
abstract void discount(double amount);
}
and two classes that extend from this base class:
class Food extends Item {
public Food(double price, String name) {
super(price, name);
}
#Override
void discount(double amount) {
this.price -= amount;
}
}
class Bevarage extends Item {
public Bevarage(double price, String name) {
super(price, name);
}
#Override
void discount(double amount) {
this.price -= amount;
}
}
Now lets make a class discount that has a List items that can discount both items.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Discount {
public void printAllContent(List<Item> items) {
items.forEach(item -> System.out.printf("name = %s, price = %.00f \n", item.getName(), item.getPrice()));
}
public static void main(String[] args) {
Discount card = new Discount();
List<Item> items = Arrays.asList(
new Food(3.0, "burgers"), new Food(9.0, "tomato"), new Food(8.0, "fries"),
new Bevarage(9.0, "cola"), new Bevarage(12.0, "water"), new Food(2.0, "beer")
);
card.printAllContent(items);
for (Item item : items) {
item.discount(1.0);
}
card.printAllContent(items);
// if you want to do different discounts for different items
for(Item item: items) {
if (item instanceof Bevarage) {
item.discount(2.0);
} else {
item.discount(1.0);
}
}
card.printAllContent(items);
}
}
java.util.List has these functions get(index) and set(index, object), which you could use:
//1. get your item
int index = 0;
Item item=content.get(index);
//2. create your discount
Discount discount=new Discount();
// Fill/process your discount object with the appropriate data
//3. replace the item with the discount in the list
content.set(index,discount);
I am trying to finish my home assignment for programming class, unfortunately getting stuck through half of it ,due to my stupidity. ArrayList that I have created overwrites 0 index constantly.
Here are my classes for creating invoices:
import java.util.ArrayList;
public class Order
{
private String customerName;
private ArrayList<LineItem> items = new ArrayList<LineItem>();
public Order(String customerName)
{
this.customerName = customerName;
}
public String getCustomerName()
{
return customerName;
}
public ArrayList<LineItem> getItems()
{
return this.items;
}
public double getOrderTotal()
{
double totalOrder = items.get(0).getTotalPrice();
return totalOrder;
}
public void addItem(String description,double unitPrice, int quantity)
{
LineItem object = new LineItem(description,unitPrice,quantity);
items.add(object);
}
public String toString()
{
String.format("%n%-20s%-15s%-15f%-15f",items.get(0).getDescription(),
items.get(0).getQuantity(),items.get(0).getUnitPrice(),getOrderTotal());
return p;`
}
}
public class LineItem
{
private String description;
private double unitPrice;
private int quantity;
public LineItem(String description,double unitPrice, int quantity)
{
this.description = description;
this.unitPrice = unitPrice;
this.quantity = quantity;
}
public String getDescription()
{
return this.description;
}
public double getUnitPrice()
{
return this.unitPrice;
}
public int getQuantity()
{
return this.quantity;
}
public double getTotalPrice()
{
return this.unitPrice * this.quantity;
}
public String toString()
{
return String(this.description,this.unitPrice,this.quantity)
}
}
AND a part of ... while LOOP for main class
do
{
customerName = AssignmentHelper.getRequiredStringInput("Please enterthe customer's name: ","A customer name must be entered!");
newOrder = new Order(customerName);
newOrder.addItem(description,unitPrice,quantity);
} while(Character.toString(userAnswer).equalsIgnoreCase ("Y"));
Your loop creates a new Order object in each iteration :
newOrder = new Order(customerName);
Each Order object has a new empty ArrayList, which is why it seems the first index is always overwritten.
If you want a single ArrayList to hold all the items, you should create a single Order object prior to the do-while loop.
newOrder = new Order(customerName);
do {
...
newOrder.addItem(description,unitPrice,quantity);
} while(Character.toString(userAnswer).equalsIgnoreCase ("Y"));
In the loop, a new order object is created which has two fields (customer name and an Arraylist of line items). Initially the ArrayList will be empty.The call to addItem object creates a new Lineitem object and add its to the ArrayList items. Therefore the lineItem object will always be added to index zero.
Create a new object only when a new customer is added.You can have a HashMap where key is the customer name. If the key already exists add to the same object else create a new order object and it to the Map.
I am trying to learn oo design pattern and developing shopping cart application where different cart items will have different types. Each type is will have some additional attributes.
Option 1: Is it good to create a separate class with every cart item with their own attributes and common attributes in base class. In this option, I will have to create multiple classes and corresponding table hierarchy in the database.
Option 2: Create single cart item with type attribute which will identify the type of the attribute. Irrelevant attributes for the particular cart item will be null in this case.
I know this is very basic question but I want to know about how people follow best practices.
Thanks in advance.
I would use Strategy for this, for example:
public interface CartItem{
String getName();
BigDecimal getPrice();
}
Only work with this interface in your shopping cart. This way, if you want a new cart item, just let it implement this interface, and it will work :)
By using an interface, you still have full freedom in how you design your actual cart items (either having 1 class, or multiple classes)
It seems to me that you do NOT want to write new code when your application has to handle new things for people to buy. Therefore, a new class when there are new items to buy is a poor design.
I was asked a similar question in an interview. The exact requirement was
Design a shopping cart with products and coupons and calculate the net price after applying coupons on products. Coupons can be of different types with certain conditions. I tried to use abstraction among Coupon/Discount processing, Cart and Product implementations classes.
N% off that is 10% off for all the individual.
D% off on next item of Type T.
D% off on next item of Type T.
Sequentially apply all the coupons on the cart and get the Total amount.
I could come up with following solution. I used CoR pattern.
import java.util.ArrayList;
import java.util.List;
interface Cart {
List<CartItem> getItems();
// void setItems(Set<CartItem> cartItems);
}
class ShoppingCart implements Cart {
private List<CartItem> items = new ArrayList<>();
boolean addItem(CartItem item) {
return items.add(item);
}
boolean removeItem(CartItem item) {
items.remove(item);
return true;
}
public List<CartItem> getItems() {
return items;
}
public double totalCartValue() {
double total = 0;
for (CartItem item : items) {
total += item.getPrice();
}
return total;
}
}
interface CartItem {
public String getName();
public double getPrice();
public void setPrice(double price);
}
abstract class Product implements CartItem {
String name;
double price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
class Card extends Product {
public Card(String name, double price) {
this.name = name;
this.price = price;
}
}
class Tshirt extends Product {
public Tshirt(String name, double price) {
this.name = name;
this.price = price;
}
}
class BackPack extends Product {
public BackPack(String name, double price) {
this.name = name;
this.price = price;
}
}
interface Coupon {
void apply(Cart cart);
void setSuccessor(Coupon successor);
}
class CouponAll implements Coupon {
private static final float DISCOUNT = 0.25f;
Coupon successor;
public void setSuccessor(Coupon successor) {
this.successor = successor;
}
public void apply(Cart cart) {
for (CartItem item : cart.getItems()) {
item.setPrice(item.getPrice() - item.getPrice() * DISCOUNT);
}
if (successor != null) {
successor.apply(cart);
}
}
}
class CouponNext implements Coupon {
private static final float DISCOUNT = 0.10f;
private int discountItemIndex;
Coupon successor;
CouponNext(int discountItemIndex) {
this.discountItemIndex = discountItemIndex;
}
public void setSuccessor(Coupon successor) {
this.successor = successor;
}
public void apply(Cart cart) {
if(discountItemIndex < cart.getItems().size()) {
CartItem cartItem = cart.getItems().get(discountItemIndex);
cartItem.setPrice(cartItem.getPrice() - cartItem.getPrice() * DISCOUNT);
}
if (successor != null) {
successor.apply(cart);
}
}
}
class CouponNextBackPack implements Coupon {
private static final float DISCOUNT = 0.15f;
private int discountItemStartIndex;
Coupon successor;
Class<?> productType;
CouponNextBackPack(int discountItemStartIndex ,Class<?> productType) {
this.discountItemStartIndex = discountItemStartIndex;
this.productType = productType;
}
public void setSuccessor(Coupon successor) {
this.successor = successor;
}
public void apply(Cart cart) {
if (discountItemStartIndex < cart.getItems().size()) {
for (int i = discountItemStartIndex; i < cart.getItems().size(); ++i) {
CartItem cartItem = cart.getItems().get(i);
if(productType.isInstance(cartItem)) {
cartItem.setPrice(cartItem.getPrice() - cartItem.getPrice() * DISCOUNT);
break;
}
}
}
if (successor != null) {
successor.apply(cart);
}
}
}
public class DriverClassCoR {
public static void main(String[] args) {
Product card1 = new Card("Card", 12.99);
Product card2 = new Card("Card", 12.99);
Product card3 = new Card("Card", 12.99);
Product tshirt1 = new Tshirt("Tshirt", 24.99);
Product tshirt2 = new Tshirt("Tshirt", 24.99);
Product backPack1 = new BackPack("BackPack", 34.99);
ShoppingCart cart = new ShoppingCart();
cart.addItem(card1); cart.addItem(card2); cart.addItem(card3);
Coupon couponAll = new CouponAll();
cart.addItem(tshirt1);
Coupon couponNext = new CouponNext(cart.getItems().size());
couponAll.setSuccessor(couponNext);
Coupon couponNextBackPack =null;
couponNextBackPack = new CouponNextBackPack(cart.getItems().size(), BackPack.class);
couponNext.setSuccessor(couponNextBackPack);
cart.addItem(tshirt2);
cart.addItem(backPack1);
System.out.println("Total car value before discounts \t" +cart.totalCartValue());
couponAll.apply(cart);
//System.out.println(backPack1.getClass().isInstance(backPack1));
System.out.println("Total car value after discounts \t" +cart.totalCartValue());
}
}
Hope this helps.
I have an inventory program written to include an array and a method to calculate total cost for all inventory items entered. I now have to include a subclass that overrides the original to include "one unique feature". I created a new file named ItemDetails to set up for the subclasses of the original Item. I need to include one unique feature and calculate the value of the inventory and calculate a 5% restocking fee in this subclass. Do I just transfer some of the relevant lines into the other class? Or do I write some code twice? I don't know what to do next. Any help is useful. Thanks. This is what I have so far:
package inventory3;
public class ItemDetails extends Items
{
public static void override()
{
private String Name;
private double pNumber, Units, Price;
public ItemDetails()
{
}
}
}
This is the Item class file that it is supposed to override:
package inventory3;
import java.lang.Comparable;
public class Items implements Comparable
{
private String Name;
private double pNumber, Units, Price;
public Items()
{
Name = "";
pNumber = 0.0;
Units = 0.0;
Price = 0.0;
}
public int compareTo(Object item)
{
Items tmp = (Items) item;
return this.getName().compareTo(tmp.getName());
}
public Items(String productName, double productNumber, double unitsInStock, double unitPrice)
{
Name = productName;
pNumber = productNumber;
Units = unitsInStock;
Price = unitPrice;
}
//setter methods
public void setName(String n)
{
Name = n;
}
public void setpNumber(double no)
{
pNumber = no;
}
public void setUnits(double u)
{
Units = u;
}
public void setPrice(double p)
{
Price = p;
}
//getter methods
public String getName()
{
return Name;
}
public double getpNumber()
{
return pNumber;
}
public double getUnits()
{
return Units;
}
public double getPrice()
{
return Price;
}
public double calculateTotalPrice()
{
return (Units * Price);
}
public static double getCombinedCost(Items[] item)
{
double combined = 0;
for(int i =0; i < item.length; ++i)
{
combined = combined + item[i].calculateTotalPrice();
}
return combined;
}
}
You simply declare a method with the same signature as the method in the parent class. So yours would look like:
package inventory3;
public class ItemDetails extends Items {
private String Name;
private double pNumber, Units, Price;
public ItemDetails(String Name, double pNumber, double Units, double Price) {
this.Name = Name;
this.pNumber = pNumber;
this.Units = Units;
this.Price = Price;
}
// getters and setters....
// The #Override is optional, but recommended.
#Override
public double calculateTotalPrice() {
return Units * Price * 1.05; // From my understanding this is what you want to do
}
}