簡體   English   中英

如何使用多態性訪問未在超 class 中使用超類的引用變量定義的子類中的方法

[英]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

如果我有 2 節課,第一個是 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());

    }
}

第二個 class 是健康漢堡

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

主要是我寫了這段代碼

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

        


    }
}

我的困惑是測試變量可以訪問healthyBurger class內部的displayBurgerDetailsWithPrices() function,並且可以調用ZC1C425268E68385D1AB5074C17A94F內部的isOnion。 而如果我決定在 main 中編寫該代碼,我將無法訪問 isOnion() function。

BasicHamburger newBurger = new HealthyBurger();
newBurger.isOnion();

為了使問題清楚明了,為什么可以通過覆蓋的 function 訪問子類內部的 function 是可能的,而當不能直接使用超類的變量訪問 function 時?

BasicHamburger newBurger = new HealthyBurger();
boolean onion = false;

if(newBurger instanceof HealthyBurger)
    onion = ((HealthyBurger).isOnion());

為了使問題清楚明了,為什么可以通過覆蓋的 function 訪問子類內部的 function 是可能的,而當無法直接使用超類的變量訪問 ZC1C425268E68385D1AB5074C17A94F14 時?

它稱為多態性。 object 參考BasicHamburger newBurger指的是 class BasicHamburger或其任何子項的實例。 這意味着默認情況下,您只能訪問在BasicHamburger或其任何父項中聲明的方法。 如果要調用子方法,則必須將此引用轉換為所需的類型。


我會重新設計您的代碼,因為在一般情況下,如果您使用強制轉換,那么它看起來像一個設計問題(重復:一般;有時確實需要)。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM