user3714598
user3714598

Reputation: 1773

Private Instance variable in an abstract class

I have an abstract class named Tea. That abstract class contains an instance variable named size and a concrete method getPrice. Now when I extend this abstract class, the value of size was not saved to variable which is the cause the problem.

What rule did I miss and why can't it save the value of size to the instance variable?

Here's my code :

package milktea;

import milktea.Drink.TeaDrink;
import milktea.Tea.Size;

public class MilkTea {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        Tea tea1 = Drink.buyTea(TeaDrink.MATCHA, Size.LARGE);
        System.out.println(tea1.getName() + "..." + tea1.getPrice());
        Sinker sinker1 = tea1.getFreeSinker();
        System.out.println(sinker1.getName() + "..." + sinker1.getPrice());

        Tea tea2 = Drink.buyTea(TeaDrink.WINTERMELON, Size.SMALL);
        System.out.println(tea2.getName() + "..." + tea2.getPrice());

    }

}

Drink.class

package milktea;

import milktea.Tea.Size;
import milktea.sinker.*;
import milktea.teaType.*;

public class Drink {

    public enum TeaDrink {
        BLACKTEA,
        CHRYSANTEMUM,
        MATCHA,
        OOLONG,
        WINTERMELON
    }

    public enum Sinkers {
        CRYSTAL,
        PEARL
    }

    public static Tea buyTea(TeaDrink tea, Size size){

        if(tea==TeaDrink.BLACKTEA){
            return new BlackTea(size);
        }else if(tea==TeaDrink.CHRYSANTEMUM){
            return new Chrysantemum(size);
        }else if(tea==TeaDrink.MATCHA){
            return new Matcha(size);
        }else if(tea==TeaDrink.OOLONG){
            return new Oolong(size);
        }else{
            return new Wintermelon(size);
        }
    }

    public static Sinker addSinker(Sinkers sinker){

        if(sinker==Sinkers.CRYSTAL){
            return new Crystal();
        }else{
            return new Pearl();
        }
    }
}

Sinker.class

package milktea;

public interface Sinker {

    String getName();
    Double getPrice();    

}

Tea.class

package milktea;

public abstract class Tea {

    public enum Size {
        LARGE, MEDIUM, SMALL
    }

    private Double largeSize;
    private Double mediumSize;
    private Double smallSize;
    private Size size;

    public abstract String getName();

    public abstract Sinker getFreeSinker();

    public Double getPrice(){
        System.out.println("LARGE " + this.size);
        if(this.size==Size.LARGE){   
            return largeSize;
        }else if(this.size==Size.MEDIUM){
            return mediumSize;
        }else if(this.size==Size.SMALL){
           return smallSize;
        }
        return 0.0;
    }

}

Matcha.class

package milktea.teaType;

import milktea.Sinker;
import milktea.Tea;
import milktea.sinker.Crystal;

public class Matcha extends Tea {

    private final Double largeSize = 3.15;
    private final Double mediumSize = 2.15;
    private final Double smallSize = 1.15;
    private final Size size;

    public Matcha(Size size){
        this.size = size;
    }

    @Override
    public String getName() {
        return "Matcha";
    }

    @Override
    public Sinker getFreeSinker() {
        return new Crystal(0.0);
    }

}

Wintermelon.class

package milktea.teaType;

import milktea.Sinker;
import milktea.Tea;
import milktea.sinker.NoFreeSinker;

public class Wintermelon extends Tea{

    private final Double largeSize = 3.15;
    private final Double mediumSize = 2.15;
    private final Double smallSize = 1.15;
    private final Size size;

    public Wintermelon(Size size){
        this.size = size;
    }

    @Override
    public String getName() {
        return "Wintermelon";
    }

    @Override
    public Sinker getFreeSinker() {
        return new NoFreeSinker();
    }   

}

Crystal.java

package milktea.sinker;

import milktea.Sinker;

public class Crystal implements Sinker{

    private Double price;

    public Crystal(Double price){
        this.price = price;
    }

    public Crystal() {
    }

    @Override
    public String getName() {
        return "Crystal";
    }

    @Override
    public Double getPrice() {
        return this.price;
    }

}

NoFreeSinker.class

package milktea.sinker;

import milktea.Sinker;

public class NoFreeSinker implements Sinker{

    @Override
    public String getName() {
        return "No free sinker.";
    }

    @Override
    public Double getPrice() {
        return 0.0;
    }

}

Pearl.class

package milktea.sinker;

import milktea.Sinker;

public class Pearl implements Sinker {

    private Double price;

    public Pearl(Double price){
        this.price = price;
    }

    public Pearl() {      
    }

    @Override
    public String getName() {
        return "Pearl";
    }

    @Override
    public Double getPrice() {
        return this.price;
    }
}

This program is a very simple Milktea system, wherein it will type the tea ordered by the customer. A tea can have a free sinker and the customer may add his/her desired sinker. Then the system will write the order and the price.

Aside from my question above, could you tell me if I have successfully coded this program in the most OOP possible?? If not, what did I do wrong?

Upvotes: 1

Views: 112

Answers (1)

Paul Hicks
Paul Hicks

Reputation: 13999

Each of your subclasses has its own definition of size, hiding the base class' size. You shouldn't define size in each class, just in the base class. Provide an accessor (Tea#getSize() by convention) which returns size so that all the subclasses can access it.

Your subclasses should call the superclass' constructor like so:

public Matcha(Size size){
    super(size);
}

Upvotes: 3

Related Questions