简体   繁体   中英

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?

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM