I got a task that I need to reduce code in the constructor but when I do as in a given example it doesn't work :(
The source code looks so:
public class Item {
private Product product;
private int stock;
Item(Product product){
this.product=product;
this.stock=0;
}
Item(Product product, int stock){
this.product=product;
this.stock=stock;
}
I tried to write it in this way:
public class Item {
private Product product;
private int stock;
Item(Product product){
this(product, 0);
}
Item(Product product, int stock){
this(product, stock);
}
Could somebody tell me please what is wrong?
There's a circular reference in the second constructor, it's calling itself. Try this instead:
// this constructor is correctly defined
public Item(Product product, int stock) {
this.product = product;
this.stock = stock;
}
// this constructor calls the other one
public Item(Product product) {
this(product, 0);
}
Your second constructor is attempting to call itself, which makes no sense.
If your class had a super class having a constructor with the same parameters, you could write :
Item(Product product, int stock){
super(product,stock);
}
Since it doesn't, you should just assign the members of the instance in the second constructor :
Item(Product product, int stock){
this.product = product;
this.stock = stock;
}
Related
Hey guys so Im new to Java and I'm having some trouble getting the hang of Interfaces, abstract classes etc.. So here I have this problem that I'm not sure to solve. Basically I have this one Interface that is susposed to be implemented by an abstract class, and that abstract class is susposed to "have" (not sure what the right term is ) a few other classes.Now I think I did the first part:
abstract class AbstractArticle implements Article {
final private String name;
final private double price;
final private String description;
AbstractArticle(String name,double price,String description) {
this.name = name;
this.price = price;
this.description = description;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public String getDescription() {
return description;
}
class Accessory extends AbstractArticle {
final String instructionsForUse;
Accessory(String name, double price, String description, String instructionsForUse) {
super(name,price,description);
this.instructionsForUse = instructionsForUse;
}
public String getinstructionsForUse() {
return instructionsForUse;
}
class Merchandise implements Article {
final private int quantity;
Article article;
Merchandise(Article article) {
this.article = article;
quantity = 0;
}
Merchandise(Article article, int quantity) {
this.article = article;
this.quantity = quantity;
}
public int getQuantity() {
return quantity;
}
public Article getArticle() {
return article;
}
}
So firstly I needed to make an abstract class override the methods and use getters to get the values, than I needed to extend the abstract class use a super constructor to call the methods getName etc.. (hopefully I did that right) and now in the class merchandise I am susposde to have 2 constructors the first one (Article article) is susposded to set the value of quantity to 0 which doesnt make sense to me,shouldn't it be done in the second constructor?Now the problem is when I try to compile the Merchandise class i get an error saying I need to make the class abstract or override the method getDescription(). Is there any way I could avoid this?
Thanks!
It looks as though you're trying to implement a Decorator Pattern: Merchandise both is a Article and has a Article.
Your Merchandise class basically wraps an existing Article and adds a quantity field to it. The idea is that a Merchandise is an "Article with a quantity".
If you want to be able to treat a Merchandise instance as an Article, you need to define the methods declared in the Article interface. Presumably here the idea is just to have those methods return the same thing the wrapped Article instance returns, which you do with:
class Merchandise implements Article {
final private int quantity;
Article article;
Merchandise(Article article) {
this.article = article;
quantity = 0;
}
Merchandise(Article article, int quantity) {
this.article = article;
this.quantity = quantity;
}
public int getQuantity() {
return quantity;
}
#Override
public String getDescription() {
return article.getDescription();
}
// and similarly for any other methods declared in Article
// you might not really want (or need) this:
public Article getArticle() {
return article;
}
}
I have made an object called Transaction which I am passing in an ArrayQueue.
Here is the Transaction class constructors (I have the appropriate setter and getters too):
public class Transaction {
private int shares;
private int price;
public Transaction(int shares, int price) {
this.shares = shares;
this.price = price;
}
public Transaction(Object obj) {
shares = obj.getShares();
price = obj.getPrice();
}
}
In the second constructor there I am wanting a scenario where I can pass into it a different Transaction object that has been dequeue(ed) and get the info from that transaction and make it into a new transaction or possibly manipulate it before I put it back into the queue. But when I compile it does not like this.
Is this acceptable programming practice to pass a specific object into it's own object's constructor? Or is this even possible?
It's called copy-constructor and you should use public Transaction(Transaction obj) instead of Object and also provide getters:
public class Transaction {
private int shares;
private int price;
public Transaction(int shares, int price) {
this.shares = shares;
this.price = price;
}
public Transaction(Transaction obj) {
this(obj.getShares(), obj.getPrice()); // Call the constructor above with values from given Transaction
}
public int getShares(){
return shares;
}
public int getPrice(){
return price;
}
}
You need to specify the same type:
public Transaction(Transaction obj) {
shares = obj.getShares();
price = obj.getPrice();
}
Provided that you have defined getShares() and getPrice().
Yes this is entirely possible.
public Transaction(Transaction other){
shares = other.shares;
price = other.price;
}
You do not need to call their getters because privacy only applies to other classes.
Yes, you can do that but you will have to type cast the parameter
public Transaction(Object obj) {
Transaction myObj = (Transaction) obj;
shares = MyObj.getShares();
price = MyObj.getPrice();
}
for instance lets assume we have a class of Author with all the getters created
to pass another object as a parameter we use the following syntax
public Author(ClassName variable){
this(obj.getlength(), obj.getwidht())// height and width are the instance variable of the class.
}
The answer to this will probably turn out to be obvious in retrospect but for now I find myself rather stuck on this. I'll give some blocks of code first and then present the problem.
This is part of my class Stockmanager, I have omitted some methods that have nothing to do with this problem.
import java.util.ArrayList;
public class StockManager
{
private ArrayList stock;
public StockManager()
{
stock = new ArrayList();
}
public void addProduct(Product item)
{
stock.add(item);
}
public Product findProduct(int id)
{
int index = 0;
while (index < stock.size())
{
Product test = stock.get(index);
if (test.getID() == id)
{
return stock.get(index);
}
index++;
}
return null;
}
public void printProductDetails()
{
int index = 0;
while (index < stock.size())
{
System.out.println(stock.get(index).toString());
index++;
}
}
}
Here's my class Product, again with some methods omitted.
public class Product
{
private int id;
private String name;
private int quantity;
public Product(int id, String name)
{
this.id = id;
this.name = name;
quantity = 0;
}
public int getID()
{
return id;
}
public String getName()
{
return name;
}
public int getQuantity()
{
return quantity;
}
public String toString()
{
return id + ": " +
name +
" voorraad: " + quantity;
}
}
My problem lies in the fact that I get a compile time error in the findProduct() method. To be more specific the line Product test = stock.get(index); is indicated with a message incompatible types.
The constructor of StockManager creates a new ArrayList with the name stock. As is evident from the method addProduct() this ArrayList contains items of the type Product. The Product class has a number of variables one of which is called id and is of type integer. That class also contains a method getID() that returns an id.
As far as I know, the way of getting an item from an arraylist is the get() method with the number between the () indicating the item's position. Seeing as my arraylist contains instances of Product, I expect to get a Product as result when I use the get() method on the arraylist. So I don't understand why it doesn't work when I define a variable called test of the type Product and try to assign an item from the arraylist to it. I have as far as I know, successfully used this same technique in the method printProductDetails() where I use the toString() method from Product on the object from the arraylist.
I hope someone will be able to clarify for me where I am at fault. If it makes any difference, I am doing this stuff in BlueJ which is probably not the best tool for it but it is the one I'm supposed to use for this school project.
private ArrayList stock;
You should redeclare this with a bounded type like so:
private List<Product> stock = new ArrayList<Product>();
If you don't, this line:
Product test = stock.get(index);
won't work because you're trying to assign a raw Object to a Product.
Others have suggested casting the Object to a Product, but I wouldn't recommend this.
Your stock is defined as private ArrayList stock, which means that stock.get() returns an Object without any special type. You should either make Stock an ArrayList of Products
ArrayList<Product> stock;
or cast the result of the get method manually
Product test = (Product)stock.get(whatever);
Product test = (Product) stock.get(index);
or if you make your list List<Product> stock your line should work without changes.
I have a method to create a list of objects of class
public List<Product> initProducts(){
List<Product> product = new ArrayList<Product>();
Product prod = new Product(product.getId(),product.getItemName(),product.getPrice(),product.getCount());
product.add(prod);
return product;
}
My Product class is:
public class Product {
int ItemCode;
String ItemName;
double UnitPrice;
int Count;
/**
* Initialise the fields of the item.
* #param Name The name of this member of product.
* #param id The number of this member of product.
* #param Price The price of this member of product.
*/
public Product(int id, String Name, double Price, int c)
{
ItemCode=id;
ItemName=Name;
UnitPrice=Price;
Count = c;
}
public int getId()
{
return this.ItemCode;
}
public String getItemName()
{
return this.ItemName;
}
public double getPrice()
{
return this.UnitPrice;
}
public int getCount()
{
return this.Count;
}
/**
* Print details about this members of product class to the text terminal.
*/
public void print()
{
System.out.println("ID: " + ItemCode);
System.out.println("Name: " + ItemName);
System.out.println("Staff Number: " +UnitPrice);
System.out.println("Office: " + Count);
}
}
I am getting an error that the method getId() is undefined for the type List<Product>, Similarly for other methods. Please help me out with this error.
Is my statement correct??
Product prod = new Product(product.getId(),product.getItemName(), product.getPrice(),
product.getCount());
product.add(prod);
product is a reference of List
List<Product> product = new ArrayList<Product>();
which doesn't have that method
product is reference to List object.
and List/ArrayList has no methosd named getId().
You have written getId() method for Prodct class , so you can call this method using ref to Product class object.
If you want to get any product object form list use get(int index) method of ArrayList.
eg.
Product prod = product.get(0);
String id= prod.getId();
I believe, the reason you are facing this issue is more due not following the code conventions, that any other.
Whenever you make a collection of any objects, the convention is to use plurals for reference names of the collection. And singular reference name of the Object itself.
You can find more details here.
Below is the re-written code with the code conventions being followed:
Method to create a list of objects of class Product:
public List<Product> initProducts(){
List<Product> products = new ArrayList<Product>();
Product product = new Product(products.getId(), products.getItemName(), products.getPrice(), products.getCount());
products.add(prod);
}
Product Class:
class Product {
int itemCode;
String itemName;
double unitPrice;
int count;
public Product(int itemCode, String itemName, double unitPrice, int count)
{
this.itemCode = itemCode;
this.itemName = itemName;
this.unitPrice = unitPrice;
this.count = count;
}
public int getId()
{
return this.itemCode;
}
public String getItemName()
{
return this.itemName;
}
public double getPrice()
{
return this.unitPrice;
}
public int getCount()
{
return this.count;
}
}
Now, it is easy to see, that the products Object (which is of the type List) will not have any methods name getId() or getCount(). Infact , these are methods of the Object contained in the List.
Following conventions will help you avoid, such hassles in futures.
Is my statement correct??
Product prod = new Product(product.getId(),product.getItemName(), product.getPrice(),
product.getCount());
product.add(prod);
NO this is incorrect. product is not an instance of class Product,rather it is an instance of List. List does not have any method called getId.
If you want to retrieve the elements from the list and use it to create another instance of you can do something like:
Product exisProd = product.get(0);
Product prod = new Product(exisProd .getId(),exisProd .getItemName(), exisProd .getPrice(),
exisProd .getCount());
But make sure that you have elements in the list, otherwise u may run into exception.
product.add(prod);
public class Item {
/**
* Instance variables for this class
*/
private String itemName;
private int itemQuantity;
/**
* Contructor for this class
*/
public Item (String itemName, int itemQuantity) {
this.itemName = itemName;
this.itemQuantity = itemQuantity;
}
//setter and getter methods
public String getItemName () {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public int getItemQuantity () {
return itemQuantity;
}
public void setItemQuantity(int itemQuantity) {
this.itemQuantity = itemQuantity;
}
}
Ok..I already have the class for item. Now I have to write the CartItem class. The description that was given are as follows:
class CartItem{
/*
Objects of this class are used to hold items that the shopper purchases in the super market.
There are two attributes in this class, an item (an object created from the Item class) and a quantity (the number of that item that the shopper purchases). You have to write these two attributes. Note that one of the two will have a user defined data type.
*/
}
public class CartItem {
private Item item; //item from the item class
private int itemQuantity; //quantity how much shopper buys
public CartItem(Item itemName, int itemQuantity) {
this.getItem();
this.getQuantity();
}
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
public int getQuantity() {
return itemQuantity;
}
public void setQuantity(int quantity) {
this.itemQuantity = itemQuantity;
}
}
Just wondering if it's correct though.
No, it's not correct. Look at your constructor:
public CartItem(Item itemName, int itemQuantity) {
this.getItem();
this.getQuantity();
}
Here you're calling the getters and completely ignoring the values the caller has passed in. I don't think you want to do that... think about what the constructor needs to do in order to populate the newly constructed object...
(You should also consider making these classes immutable, but that's a slightly different matter.)
Few things.
1 Person may shop more than one Item so have List of Item
2 Constructor isn't correct, which should be
public CartItem(Item itemName, int itemQuantity) {
this.item = itemName;
this.itemQuantity = itemQuantity;
}
No it's not.
The constructor for CartItem just calls this.getItem() and this.getQuantity(). This will just call the methods, which will obviously return null, since the attributes are never initialized. It should be:
public CartItem(Item itemName, int itemQuantity) {
this.item = itemName;
this.itemQuantity = itemQUantity;
}
Another problem is that you add getters and setters for all the fields, without even knowing if those methods are necessary. Try to favor immutability, and only provide setters if they are absolutely necessary. I won't explain all the advantages of immutability, because it would be too early given what you already know. But a good rule of thumb is : don't add a method to a class if it's not used.