Search code examples
javapolymorphismsubclasssuperclass

Minor issue when working with extended classes in Java


edit: this was entirely my error, likely due to rushing things at 4am. The code was technically sound and working fine, though thank to the comments I have removed some redundancy to make things a bit smarter.

I'm working on a class project that deals with Java super/subclasses and inheritance. While 90% of the code works just fine, one minor thing doesn't seem to want to work and I'm a bit perplexed as to why. Basically, we're creating a new class called CompactDisc that contains information such as product code, Description, Price, and Artist. When the user enters the appropriate code (sgtp), the console will output the information. Unfortunately the Artist line is always blank, despite giving it data. While there are other classes involved with this project, I'll will only post the ones I feel are important.

ProductApp.java:

import java.util.Scanner;

public class ProductApp
{
    public static void main(String args[])
    {
        // display a weclome message
        System.out.println("Welcome to the Product Selector\n");

        // perform 1 or more selections
        Scanner sc = new Scanner(System.in);
        String choice = "y";
        while (choice.equalsIgnoreCase("y"))
        {
            System.out.print("Enter product code: ");
            String productCode = sc.next();  // read the product code
            sc.nextLine();  // discard any other data entered on the line

            // get the Product object
            Product p = ProductDB.getProduct(productCode);

            // display the output
            System.out.println();
            if (p != null)
                System.out.println(p.toString());
            else
                System.out.println("No product matches this product code.\n");

            System.out.println("Product count: " + Product.getCount() + "\n");

            // see if the user wants to continue
            System.out.print("Continue? (y/n): ");
            choice = sc.nextLine();
            System.out.println();
        }
    }
}

Product.java:

import java.text.NumberFormat;

public class Product
{
    private String code;
    private String description;
    private String artist;
    private double price;
    protected static int count = 0;

    public Product()
    {
        code = "";
        description = "";
        price = 0;

    }

    public void setCode(String code)
    {
        this.code = code;
    }

    public String getCode(){
        return code;
    }

    public void setArtist(String artist)
    {
        this.artist = artist;
    }

    public String getArtist(){
        return artist;
    }

    public void setDescription(String description)
    {
        this.description = description;
    }

    public String getDescription()
    {
        return description;
    }

    public void setPrice(double price)
    {
        this.price = price;
    }

    public double getPrice()
    {
        return price;
    }

    public String getFormattedPrice()
    {
        NumberFormat currency = NumberFormat.getCurrencyInstance();
        return currency.format(price);
    }

    @Override
    public String toString()
    {
        return "Code:        " + code + "\n" +
               "Description: " + description + "\n" +
               "Price:       " + this.getFormattedPrice() + "\n";
    }

    public static int getCount()
    {
        return count;
    }
}

CompactDisc.java:

public class CompactDisc extends Product
{
    private String artist;

    public CompactDisc()
    {
        super();
        artist = "";
        count++;
    }

        @Override
    public void setArtist(String artist)
    {
        this.artist = artist;
    }

    @Override
        public String getArtist(){
        return artist;
    }

        @Override
    public String toString()
    {
        return super.toString() +
            "Artist:      " + artist + "\n";
    }
}

ProductDB.java:

public class ProductDB
{
    public static Product getProduct(String productCode)
    {
        // In a more realistic application, this code would
        // get the data for the product from a file or database
        // For now, this code just uses if/else statements
        // to return the correct product data

        Product p = null;

        if (productCode.equalsIgnoreCase("java") ||
           productCode.equalsIgnoreCase("jsps") ||
           productCode.equalsIgnoreCase("mcb2"))
        {
            Book b = new Book();
            if (productCode.equalsIgnoreCase("java"))
            {
                b.setCode(productCode);
                b.setDescription("Murach's Beginning Java");
                b.setPrice(49.50);
                b.setAuthor("Andrea Steelman");
            }
            else if (productCode.equalsIgnoreCase("jsps"))
            {
                b.setCode(productCode);
                b.setDescription("Murach's Java Servlets and JSP");
                b.setPrice(49.50);
                b.setAuthor("Andrea Steelman");
            }
            else if (productCode.equalsIgnoreCase("mcb2"))
            {
                b.setCode(productCode);
                b.setDescription("Murach's Mainframe COBOL");
                b.setPrice(59.50);
                b.setAuthor("Mike Murach");
            }
            p = b; // set Product object equal to the Book object
        }
        else if (productCode.equalsIgnoreCase("txtp"))
        {
            Software s = new Software();
            s.setCode("txtp");
            s.setDescription("TextPad");
            s.setPrice(27.00);
            s.setVersion("4.7.3");
            p = s; // set Product object equal to the Software object
        }
 else if (productCode.equalsIgnoreCase("sgtp"))
        {
            CompactDisc c = new CompactDisc();
            c.setCode("sgtp");
            c.setDescription("Sgt. Pepper's Lonely Hearts Club Band");
            c.setPrice(15.00);
            c.setArtist("The Beatles");
            p = c; // set Product object equal to the CompactDisc object
        }
        return p;
        }

And the output. As you can see Artist is empty:

Welcome to the Product Selector

Enter product code: sgtp

Code:        sgtp
Description: Sgt. Pepper's Lonely Hearts Club Band
Price:       $15.00
Artist:      

Product count: 1

Continue? (y/n): 

I have a hunch I did something wrong in ProductDB.java, but I could be wrong. Thanks in advance.


Solution

  • Your problem exists because of the declaration

     Product p
    

    and later became

     Product p = new CompactDisc();
    

    That line means, your variables still refer to type Product and the methods from CompactDisc

    Change

      @Override
    public String toString()
    {
        return super.toString() +
            "Artist:      " + artist + "\n";
    }
    

    to

      @Override
    public String toString()
    {
        return super.toString() +
            "Artist:      " + this.getArtist() + "\n";
    }
    

    When you are printing a varaible it still points to the LHS of the declaration and when you access a method it belongs to RHS.

    As a side note, you have a design issues (commented the same earlier) as well by having multiple artist variables in parent and aswell as child. remove that at one level and make your program more clear.