Interface references - java

I'm not sure how to address this question. Here is my code:
public interface Stuff {
public String description();
public double weight();
}
class Bag implements Stuff {
public String description() {
return "bag of";
}
public double weight() {
return 10.50;
}
}
class StuffWrapper implements Stuff {
Stuff item;
public StuffWrapper(Stuff item) {
this.item = item;
}
public String description() {
return item.description();
}
public double weight() {
return item.weight();
}
}
class Material extends StuffWrapper {
String material;
double weight;
public Material(Stuff item, String material, double weight) {
super(item);
this.material = material;
this.weight = weight;
}
public String description() {
return item.description() + " :" + material+ ":";
}
public double weight() {
return item.weight() + weight;
}
}
and then I have this:
Stuff icStuff = new Bag();
icStuff = new Material(icStuff, "leather", 10.30);
icStuff = new Material(icStuff, "plastic", 20.50);
System.out.println(icStuff.description() + Double.toString(icStuff.weight()));
which outputs
bag of :leather: :plastic:41.3
After doing all of that if I wanted icStuff to no longer reference this:
icStuff = new Material(icStuff, "plastic", 20.50);
How should I do it?

assign it to something else, or null, or whatever you want it to reference
icStuff = null;
icStuff = Somethingelse;

Related

How to use polymorphism to access a method inside a subclass that is not defined in the super class using a reference variable of a superclass

If i have 2 classes the first one is BasicHamburger
public class BasicHamburger {
private String breadRollType;
private String meat;
private boolean lettuce;
private boolean tomato;
private boolean carrot;
private boolean cheese;
private int numberOfAdditions;
private int price;
public BasicHamburger(String breadRollType , String meat ,int price){
this.breadRollType = breadRollType;
this.meat = meat;
this.price = price;
lettuce = false;
tomato = false;
carrot = false;
cheese = false;
numberOfAdditions = 0;
}
public void addLettuce(){
lettuce = true;
incrementNumberOfAdditions();
}
public void addTomato(){
tomato = true;
incrementNumberOfAdditions();
}
public void addCarrot(){
carrot = true;
incrementNumberOfAdditions();
}
public void addCheese(){
cheese = true;
incrementNumberOfAdditions();
}
public int getNumberOfAdditions(){
return numberOfAdditions;
}
protected int incrementNumberOfAdditions(){
return ++numberOfAdditions;
}
public boolean isLettuce() {
return lettuce;
}
public boolean isTomato() {
return tomato;
}
public boolean isCarrot() {
return carrot;
}
public boolean isCheese() {
return cheese;
}
public int getBasicHamburgerPrice(){
return price;
}
public int getLettucePrice(){
return 20;
}
public int getTomatoPrice(){
return 15;
}
public int getCheesePrice(){
return 40;
}
public int getCarrotPrice(){
return 10;
}
public int getTotalBasicHamburgerPrice(){
if(isCarrot()){
price = price + 10;
}
if(isCheese()){
price = price + 40;
}
if(isTomato()){
price = price + 15;
}
if(isLettuce()){
price = price + 20;
}
return price;
}
public void displayBurgerDetailsWithPrices(){
if(isCarrot()){
System.out.println("Carrot addition = "+getCarrotPrice());
}
if(isCheese()){
System.out.println("Cheese addition = "+getCheesePrice());
}
if(isTomato()){
System.out.println("Tomato addition = "+getTomatoPrice());
}
if(isLettuce()){
System.out.println("Lettuce addition = "+getLettucePrice());
}
System.out.println("Basic Hamburger Total Price Without Additions = "+getBasicHamburgerPrice());
System.out.println("Basic Hamburger Total Price After Additions= "+getTotalBasicHamburgerPrice());
}
}
the second class is HealthyBurger
public class HealthyBurger extends BasicHamburger{
private boolean onion;
private boolean bacon;
public HealthyBurger(){
super("Brown Rye ","Mutton",30);
onion = false;
bacon = false;
}
public boolean isOnion() {
return onion;
}
public boolean isBacon() {
return bacon;
}
public void addOnion(){
onion = true;
incrementNumberOfAdditions();
}
public void addBacon(){
bacon = true;
incrementNumberOfAdditions();
}
public int getOnionPrice(){
return 15;
}
public int getBaconPrice(){
return 20;
}
#Override
public int getTotalBasicHamburgerPrice() {
int newPrice = super.getTotalBasicHamburgerPrice();
if(isBacon()){
newPrice += 20;
}
if(isOnion()){
newPrice +=15;
}
return newPrice;
}
#Override
public void displayBurgerDetailsWithPrices() {
if(isCarrot()){
System.out.println("Carrot addition = "+getCarrotPrice());
}
if(isCheese()){
System.out.println("Cheese addition = "+getCheesePrice());
}
if(isTomato()){
System.out.println("Tomato addition = "+getTomatoPrice());
}
if(isLettuce()){
System.out.println("Lettuce addition = "+getLettucePrice());
}
if(isOnion()){
System.out.println("Onion addition = "+getOnionPrice());
}
if(isBacon()){
System.out.println("Bacon addition = "+getBaconPrice());
}
System.out.println("Healthy Hamburger Total Price Without Additions = "+getBasicHamburgerPrice());
System.out.println("Healthy Hamburger Total Price After Additions= "+getTotalBasicHamburgerPrice());
}
}
in the main i have written this code
public class Main {
public static void DisplayBurger(BasicHamburger burger){
burger.displayBurgerDetailsWithPrices();
}
public static void main(String[] args) {
BasicHamburger ham1 = new BasicHamburger("x","beef",20);
ham1.addCarrot();
ham1.addCheese();
ham1.addLettuce();
ham1.addTomato();
HealthyBurger ham2 = new HealthyBurger();
ham2.addOnion();
ham2.addBacon();
BasicHamburger test = ham2;
DisplayBurger(test);
}
}
My confusion is the test variable can access displayBurgerDetailsWithPrices() function inside HealthyBurger class and can call the isOnion which is inside that function. Whereas if i decided to write that code inside the main i can not access the isOnion() function.
BasicHamburger newBurger = new HealthyBurger();
newBurger.isOnion();
To make the question clear and right to the point , why accessing a function inside a subclass through a overriden function is possible whereas accessing that function directly is not possible when using a variable of the superclass?
BasicHamburger newBurger = new HealthyBurger();
boolean onion = false;
if(newBurger instanceof HealthyBurger)
onion = ((HealthyBurger).isOnion());
To make the question clear and right to the point, why accessing a function inside a subclass through an overridden function is possible whereas accessing that function directly is not possible when using a variable of the superclass?
It calles Polymophism. The object reference BasicHamburger newBurger refers to the instance of class BasicHamburger or any of its children. It means that by default you have access only to the methods declared in BasicHamburger or any of its parent. If you want to call the children's method, you have to cast this reference to the required type.
I would redesign your code, because in general case if you use casting, then it looks like a design problem (repeat: in general; sometimes it really needed).
public abstract class Burger {
protected final String breadRollType;
protected final String meat;
protected final int basePrice;
protected final Set<Ingredient> ingredients;
protected Burger(String breadRollType, String meat, int basePrice, Set<Ingredient> ingredients) {
this.breadRollType = breadRollType;
this.meat = meat;
this.basePrice = basePrice;
this.ingredients = ingredients == null || ingredients.isEmpty() ? Set.of() : Set.copyOf(ingredients);
}
public final int getBasePrice() {
return basePrice;
}
protected int getIngredientsPrice() {
return ingredients.stream()
.map(Ingredient::getPrice)
.mapToInt(i -> i)
.sum();
}
public int getTotalPrice() {
return basePrice + getIngredientsPrice();
}
public final int getTotalIngredients() {
return ingredients.size();
}
public final boolean hasIngredient(Ingredient ingredient) {
return ingredient != null && ingredients.contains(ingredient);
}
public void printDetailsWithPrices() {
System.out.println(breadRollType + ' ' + meat);
System.out.println("----");
System.out.println("Basic price: " + basePrice);
System.out.println("Ingredients price: " + getIngredientsPrice());
ingredients.forEach(ingredient -> System.out.format("-> %s price: %d\n",
ingredient.getTitle(), ingredient.getPrice()));
System.out.println("Total price: " + getTotalPrice());
}
protected interface Ingredient {
String getTitle();
int getPrice();
}
}
public class HealthyBurger extends Burger {
public HealthyBurger(String breadRollType, String meat, int basePrice, Set<Burger.Ingredient> ingredients) {
super(breadRollType, meat, basePrice, ingredients);
}
public enum Ingredient implements Burger.Ingredient {
ONION("Onion", 15),
BACON("Bacon", 20);
private final String title;
private final int price;
Ingredient(String title, int price) {
this.title = title;
this.price = price;
}
#Override
public String getTitle() {
return title;
}
#Override
public int getPrice() {
return price;
}
}
}
public class PopularBurger extends Burger {
protected PopularBurger(String breadRollType, String meat, int basePrice, Set<Burger.Ingredient> ingredients) {
super(breadRollType, meat, basePrice, ingredients);
}
public enum Ingredient implements Burger.Ingredient {
LETTUCE("Lettuce", 20),
TOMATO("Tomato", 25),
CARROT("Carrot", 10),
CHEESE("Cheese", 40);
private final String title;
private final int price;
Ingredient(String title, int price) {
this.title = title;
this.price = price;
}
#Override
public String getTitle() {
return title;
}
#Override
public int getPrice() {
return price;
}
}
}
public static void main(String... args) {
PopularBurger popularBurger = new PopularBurger("x", "beef", 20,
Set.of(PopularBurger.Ingredient.CARROT,
PopularBurger.Ingredient.CHEESE,
PopularBurger.Ingredient.LETTUCE,
PopularBurger.Ingredient.TOMATO));
HealthyBurger healthyBurger = new HealthyBurger("Brown Rye", "Mutton", 30,
Set.of(HealthyBurger.Ingredient.ONION,
HealthyBurger.Ingredient.BACON));
PopularBurger one = popularBurger;
one.printDetailsWithPrices();
System.out.println();
HealthyBurger two = healthyBurger;
two.printDetailsWithPrices();
System.out.println();
boolean withOnion = two.hasIngredient(HealthyBurger.Ingredient.ONION);
System.out.println(withOnion);
}
x beef
----
Basic price: 20
Ingredients price: 95
-> Cheese price: 40
-> Carrot price: 10
-> Lettuce price: 20
-> Tomato price: 25
Total price: 115
Brown Rye Mutton
----
Basic price: 30
Ingredients price: 35
-> Onion price: 15
-> Bacon price: 20
Total price: 65
true

Using arbitrary number of classes

I would appreciate any help in solving the following question.
Design and implement a subclass of GenericOrder called ComputerPartyOrder that takes an arbitrary number of different classes of ComputerPart objects, Peripheral objects, Cheese objects, Fruit objects and Service objects.
here is the code for Product class and GerericOrder class.
abstract class Product {
protected float price;
// return the price of a particular product
abstract float price();
//public getType() {
//
//}
}
//------------------------------------------------------------
class ComputerPart extends Product {
public ComputerPart(float p) {
price = p;
}
public float price() { return price; }
}
class Motherboard extends ComputerPart {
protected String manufacturer;
public Motherboard(String mfg, float p) {
super(p);
manufacturer = mfg;
}
public String getManufacturer() { return manufacturer; }
}
class RAM extends ComputerPart {
protected int size;
protected String manufacturer;
public RAM(String mfg, int size, float p) {
super(p);
this.manufacturer = mfg;
this.size = size;
}
public String getManufacturer() { return manufacturer; }
}
class Drive extends ComputerPart {
protected String type;
protected int speed;
public Drive(String type, int speed, float p) {
super(p);
this.type = type;
this.speed = speed;
}
public String getType() { return type; }
public int getSpeed() { return speed; }
}
class Peripheral extends Product {
public Peripheral(float p) {
price = p;
}
public float price() { return price; }
}
class Printer extends Peripheral {
protected String model;
public Printer(String model, float p) {
super(p);
this.model = model;
}
public String getModel() { return model; }
}
class Monitor extends Peripheral {
protected String model;
public Monitor(String model, float p) {
super(p);
this.model = model;
}
public String getModel() { return model; }
}
class Service extends Product {
public Service(float p) {
price = p;
}
public float price() { return price; }
}
class AssemblyService extends Service {
String provider;
public AssemblyService(String pv, float p) {
super(p);
provider = pv;
}
public String getProvider() { return provider; }
}
class DeliveryService extends Service {
String courier;
public DeliveryService(String c, float p) {
super(p);
courier = c;
}
public String getCourier() { return courier; }
}
//-------------------------------------------------------
class Cheese extends Product {
public Cheese(float p) {
price = p;
}
public float price() { return price; }
}
class Cheddar extends Cheese {
public Cheddar(float p) {
super(p);
}
}
class Mozzarella extends Cheese {
public Mozzarella(float p) {
super(p);
}
}
class Fruit extends Product {
public Fruit(float p) {
price = p;
}
public float price() { return price; }
}
class Apple extends Fruit {
public Apple(float p) {
super(p);
}
}
class Orange extends Fruit {
public Orange(float p) {
super(p);
}
}
GenericOrder:
import java.util.ArrayList;
import java.util.List;
public abstract class GenericOrder<T> extends Product {
private static long counter = 1;
private final long id = counter++;
private List<T> Item;
public GenericOrder() {
Item = new ArrayList<T>();
}
public long getid() {
return id;
}
public void addItem(T newItem) {
Item.add(newItem);
}
public List<T> getItem() {
return Item;
}
public void setItem(List<T> Item) {
this.Item = Item;
}
}
EDIT: Code so far
public abstract class ComputerPartyOrder extends GenericOrder {
GenericOrder GOrder = new GenericOrder() {
#Override
float price() {
return 0;
}
};
public void input(Product newitem) {
GOrder.addItem(newitem);
}
public void output() {
System.out.println(GOrder.getItem());
}
}
You have the right idea, but GenericOrder does not need a type parameter T. Instead, you can set the type of Item to Product (the superclass of all the different types of products).
public abstract class GenericOrder extends Product {
private static long counter = 1;
private final long id = counter++;
private List<Product> Item;
public GenericOrder() {
Item = new ArrayList<Product>();
}
public long getid() {
return id;
}
public void addItem(Product newItem) {
Item.add(newItem);
}
public List<Product> getItem() {
return Item;
}
public void setItem(List<Product> Item) {
this.Item = Item;
}
}
You will still be able to call addItem with any instance of a subclass of Product.
I would also suggest renaming Item to item, uppercase names are usually used for types, not variables.

no suitable constructor found(Java)

Trying to create object using aggregation but error shows no suitable constructor when using array to create objects. What I'm trying to understand is why wont the array identify the information implemented as I when I don't provide information on the object it is able to create an object with it's default information from both class' no-arg constructor
public class ComputerTest {
public static void main(String[] args){
Computer c[] = new Computer[5];
c[0] = new Computer("OEM", "Basic");
c[1] = new Computer("Dell", "Optiplex", "discrete", "PCIEx16", 375, "8-pin",16);
c[2] = new Computer("Lenova","IdeaCentre", "integrated", "N/A", 120, "N/A", 4);
c[3] = new Computer("HP", "Omen Obelisk", "discrete", "PCIEx8", 150,"6-pin", 8);
c[4] = new Computer("Lenovo" , "IdeaCentre", "integrated", "N/A", -110, "N/A", 2);
printComputers(c);
}
static void printComputers(Computer c[]){
for (int i=0; i<c.length; i++){
System.out.println(c[i].getInfo());
}
}
Using information from this class
public class Computer {
private String brand;
private String model;
private VideoCard VideoCard;
public Computer(){
this.setBrand("OEM");
this.setModel("Basic");
this.VideoCard = new VideoCard();
}
public Computer(String brand, String model, VideoCard VideoCard){
this.setBrand(brand);
this.setModel(model);
this.setVideoCard(VideoCard);
}
public void setBrand(String brand){
this.brand = brand;
}
public void setModel(String model){
this.model = model;
}
public void setVideoCard(VideoCard VideoCard){
this.VideoCard = VideoCard;
}
public String getBrand(){
return brand;
}
public String getModel(){
return model;
}
public VideoCard getVideoCard(){
return this.VideoCard;
}
public String getInfo(){
String info = String.format("%s " + "%s\n" + "Video Card Info:\n" + "%s\n", getBrand(), getModel(), VideoCard.getInfo());
return info;
}
which aggregates from this class
public class VideoCard {
private String type;
private String connection;
private int power;
private String extPower;
private int memory;
public VideoCard(){
this.setType("integrated");
this.setConnection("N/A");
this.setPower(100);
this.setExtPower("N/A");
this.setMemory(1);
}
public VideoCard(String type, String connection, int power, String extPower, int memory){
this.setType(type);
this.setConnection(connection);
this.setPower(power);
this.setExtPower(extPower);
this.setMemory(memory);
}
public void setType(String type){
this.type = type;
}
public void setConnection(String connection){
this.connection = connection;
}
public void setPower(int power){
if(power>= 1 && power<=300){
this.power = power;
} if(power<1) {
this.power = 75;
} if(power>300){
this.power = 200;
}
}
public void setExtPower(String extPower){
this.extPower = extPower;
}
public void setMemory(int memory){
if(memory>=1 && memory<=12){
this.memory = memory;
} if(memory<1){
this.memory = 1;
} if(memory>12){
this.memory = 12;
}
}
public String getType(){
setType(this.type);
return type;
}
public String getConnection(){
setConnection(this.connection);
return connection;
}
public int getPower(){
setPower(this.power);
return power;
}
public String getExtPower(){
setExtPower(this.extPower);
return extPower;
}
public int getMemory(){
setMemory(this.memory);
return memory;
}
public String getInfo(){
String info = String.format("Type:\t\t%s\n " + "Connection:\t%s\n " + "Power:\t\t%sW \n " + "Ext Power:\t%s\n " + "Memory:\t%dGB \n ",
getType(), getConnection(), getPower(), getExtPower(), getMemory());
return info;
}

How to iterate over generic list

I have a class in that I take one list of generic type. Now I am trying to iterate over that list to get the value of that class. In getOrderAmount() method I trying to iterate.
#Document(collection = Cart.FIELDS.COLLECTION)
public class Cart extends BaseOrderEntity {
public interface FIELDS extends BaseOrderEntity.FIELDS {
String COLLECTION = "cart";
String LIST_ORDERS = "orderList";
String CART_TYPE = "cartType";
}
#Field(value = FIELDS.LIST_ORDERS)
private List<T> orderList;
#Field(value = FIELDS.CART_TYPE)
private Integer cartType;
public List<T> getOrderList() {
return orderList;
}
public void setOrderList(List<T> orderList) {
this.orderList = orderList;
}
public Integer getCartType() {
return cartType;
}
public void setCartType(Integer cartType) {
this.cartType = cartType;
}
#Override
public RefCollectionType getRefCollectionType() {
if (T.class.getClass() == FoodItemOrderDetails.class.getClass()) {
return RefCollectionType.FOOD;
} else if (T.class.getClass() == LaundryItemOrderDetails.class.getClass()) {
return RefCollectionType.LAUNDRY;
} else if (T.class.getClass() == HousekeepingItemOrderDetails.class.getClass()) {
return RefCollectionType.HOUSEKEEPING;
}
return RefCollectionType.FOOD;
}
#Override
public double getOrderAmount() {
double totalfoodOrderAmount = 0.0;
for (FoodItemOrderDetails foodItem : orderList) {
totalfoodOrderAmount = totalfoodOrderAmount + (foodItem.getPrice() * foodItem.getQuantity());
}
return totalfoodOrderAmount;
}
}
The generic classes are here.
FoodItemOrderDetails
LaundryItemOrderDetails
HousekeepingItemOrderDetails
You should have an interface like OrderDetails which should have 2 methods getQuantity() and getPrice(). Now implement that interface in FoodItemOrderDetails,
LaundryItemOrderDetails, HousekeepingItemOrderDetails.
for (OrderDetails item : orderList) {
totalAmount = totalAmount + (item .getPrice() * item.getQuantity());
}
Your Interface should looks like below.
interface OrderDetails {
Double getPrice();
Integer getQuantity();
}
Your classes should look like below.
class FoodItemOrderDetails implements OrderDetails {
#Override
public Double getPrice() {
// return the price for FoodItem
return null;
}
#Override
public Integer getQuantity() {
// return the Quantity for FoodItem
return null;
}
}
You can use Java-8 stream.
List<OrderDetails> details = new ArrayList<>();
double total = details.stream().mapToDouble(e -> e.getPrice() * e.getQuantity()).sum();

Created add() method to insert objects into an array and all i get are null values

this is a class called Doglist to add the object to an array.
public class DogList {
private int numItems;
private DogItem[] dogListArray;
private int position;
DogList () {
numItems=0;
position = 0;
dogListArray = new DogItem[10];
}
public void add (DogItem item) {
dogListArray[numItems++]= new DogItem(item.getName(),
item.getBreed(),
item.getWeight(),
item.getOwner1(),
item.getOwner2()
);
}
public String toString() {
String result = "";
for (int i=0; i<numItems; i++) {
result += dogListArray[i].toString() + "\n";
}
return result;
}
public DogItem searchForDogItem (DogItem gi) {
System.out.println("Here is your obj value: " + gi );
return null;
}//This is the one im having trouble with.
}
I have all the setters and getters in the DogItem class.
and this is from the UI where i get the dog info(name, breed, weight, owners1&2 names)
public void searchForItem (String name ) {
DogItem gi = new DogItem (name);
gi = gl.searchForDogItem(gi);
if (gi==null) {
msgTextField.setText("Dog Not Found");
} else {
nameTextField.setText(String.valueOf(gi.getName()));
breedTextField.setText(String.valueOf(gi.getBreed()));
weightTextField.setText(String.valueOf(gi.getWeight()));
owner1TextField.setText(String.valueOf(gi.getOwner1()));
owner2TextField.setText(String.valueOf(gi.getOwner2()));
}
}
Ill try and clear things up as i go.
this is the output i get
Here is your obj value: null null 0.0 null null
Ok so here is what it probably should look like instead. Just from what I saw wrong already. However you'd probably want to override the toString() method of DogItem.
Main method example of this:
public class Main {
public static void main(String[] args) {
DogItem dogItem = new DogItem("Spot", "Dalmation", "45", "Bob", "Sandy");
DogItem.add(dogItem);
DogItem result = DogItem.searchForItem("Spot");
if (result == null) {
System.out.println("Dog not found");
// GUI error output goes here
} else {
System.out.println("Here is your obj value: " + result);
// Where your GUI stuff goes
}
}
}
DogItem example of this:
public class DogItem {
private static DogItem[] dogListArray = new DogItem[100];
private static int numItems = 0;
private String name;
private String breed;
private String weight;
private String owner1;
private String owner2;
public DogItem(String name, String breed, String weight, String owner1, String owner2) {
this.name = name;
this.breed = breed;
this.weight = weight;
this.owner1 = owner1;
this.owner2 = owner2;
}
public static void add(DogItem dogItem) {
dogListArray[numItems++] = dogItem;
}
public static DogItem searchForItem(String name) {
DogItem dogItem = null;
for (DogItem result : dogListArray) {
if (result != null) {
if (result.getName() == name) {
dogItem = result;
}
}
}
return dogItem;
}
#Override
public String toString() {
String result = name + ", " + breed + ", " + weight + ", " + owner1 + " " + owner2;
return result;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBreed() {
return breed;
}
public void setBreed(String breed) {
this.breed = breed;
}
public String getWeight() {
return weight;
}
public void setWeight(String weight) {
this.weight = weight;
}
public String getOwner1() {
return owner1;
}
public void setOwner1(String owner1) {
this.owner1 = owner1;
}
public String getOwner2() {
return owner2;
}
public void setOwner2(String owner2) {
this.owner2 = owner2;
}
}
These would be recommended changes from me though:
private static ArrayList<String> owners;
private static ArrayList<DogItem> dogsList;
public DogItem(String name, String breed, String weight, String owner) {
this.name = name;
this.breed = breed;
this.weight = weight;
this.owners.add(owner);
}
public void init() {
owners = new ArrayList<String>();
dogsList = new ArrayList<DogItem>();
}
public void addDog(DogItem dogItem) {
dogsList.add(dogItem);
}
public DogItem searchForItem(String name) {
DogItem dogItem = null;
for (DogItem result : dogsList) {
if (result != null) {
if (result.getName() == name) {
dogItem = result;
}
}
}
return dogItem;
}
public void addOwner(String owner) {
owners.add(owner);
}
public String getOwner() {
return owners.get(owners.size() - 1);
}

Categories