![](/img/trans.png)
[英]Java polymorphism - How to determine whether superclass vs subclass method will be called and superclass variable vs subclass variable?
[英]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.