![](/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.