Java 如何使子类的字段和方法可用于仅通过另一个类使用超类的类

Java 如何使子类的字段和方法可用于仅通过另一个类使用超类的类,java,inheritance,Java,Inheritance,所以,在论坛上搜索了几个小时后,我找不到任何对我有帮助的答案,所以我来了 我正在尝试制作一款垄断风格的游戏,我正在制作游戏引擎类。 我有一个“Board”类和一个“abstract Card”类,我用它来制作其他几个类,如“HouseCard”、“Decision Card”、“AirportCard”等。 正如您所看到的,每个卡片类都有不同的方法和字段。 我现在正在尝试创建游戏引擎类,我需要访问其中一些类的一些字段和一些方法,但我不能。Eclipse给我的唯一可能的解决方案是在“抽象卡”类中创

所以,在论坛上搜索了几个小时后,我找不到任何对我有帮助的答案,所以我来了

我正在尝试制作一款垄断风格的游戏,我正在制作游戏引擎类。 我有一个“Board”类和一个“abstract Card”类,我用它来制作其他几个类,如“HouseCard”、“Decision Card”、“AirportCard”等。 正如您所看到的,每个卡片类都有不同的方法和字段。 我现在正在尝试创建游戏引擎类,我需要访问其中一些类的一些字段和一些方法,但我不能。Eclipse给我的唯一可能的解决方案是在“抽象卡”类中创建方法,并在子类中创建@Override,但这是不对的,因为我必须在所有其他类中实现这些方法,所以最终每个类中都会有30个方法,这是错误的。 我提供了一些代码来理解我的意思,因为我已经对两个抽象布尔方法和一个int做了这个解决方案,但它已经感觉不对了

这是卡片类:

public abstract class Card {
    
    public Card() {
    }
    
    public void stringCard() {
    }
    
    public void setHolder(int holderID) {
    }
    
    public abstract Boolean hasOwner();
    public abstract Boolean buyable();
    public abstract int getBuyCost();
}
这是我使用的“HouseCard”类的卡片子类之一:

public class HouseCard extends Card{
    
    public String cardName;
    public int buycost, rent, h1, h2, h3, h4, hotel, mortgage, hcost;
    public int holderID = -1;
    
    public HouseCard(String cardName, int buycost, int rent, int h1, int h2, int h3, int h4, int hotel, int mortgage, int hcost) {
        this.cardName = cardName;
        this.buycost = buycost;
        this.rent = rent;
        this.h1 = h1;
        this.h2 = h2;
        this.h3 = h3;
        this.h4 = h4;
        this.hotel = hotel;
        this.mortgage = mortgage;
        this.hcost= hcost;
    }
    
    @Override
    public void setHolder(int holderID) {
        this.holderID = holderID;
    }

    @Override
    public Boolean buyable() {
        if (this.holderID == -1) {
            return true;
        }
        else {
            return false;
        }
    }
    
    @Override
    public Boolean hasOwner() {
        if (this.holderID == -1) {
            return false;
        }
        else {
            return true;
        }
    }
    
    @Override
    public int getBuyCost() {
        return buycost;
    }
    
    @Override
    public void stringCard() {
        System.out.println("      " + cardName + " (" + buycost + "$)");
        System.out.println("");
        System.out.println("Rent Pay    -> " + rent + "$");
        System.out.println("1st House   -> " + h1 + "$");
        System.out.println("2nd House   -> " + h2 + "$");
        System.out.println("3rd house   -> " + h3 + "$");
        System.out.println("4th house   -> " + h4 + "$");
        System.out.println("");
        System.out.println("Hotel       -> " + hotel + "$");
        System.out.println("");
        System.out.println("Mortgage    -> " + mortgage + "$");
        System.out.println("");
    }
    
    public String getCardName() {
        return cardName;
    }
}
这是我用来存储游戏中每个方块的棋盘类,对不同的牌使用不同的方法:

public class Board {
    
    public ArrayList<Card> Cards;
    public int numberBoard = 0;
    
    public Board(){
        this.Cards = new ArrayList<Card>();
    }
    
    public void addCard(String cardName, String cardDesc) {
        Card card = new GeneralCard(cardName, cardDesc);
        Cards.add(card);
        numberBoard++;
    }
    
    public void addCard(String cardName, String cardDesc, Action action) {
        Card card = new GeneralCard(cardName, cardDesc, action);
        Cards.add(card);
        numberBoard++;
    }
    
    public void addCardMulti(String cardName, int buycost, int pay1, int pay2, int mortgage) {
        Card card = new MultiCard(cardName, buycost, pay1, pay2, mortgage);
        Cards.add(card);
        numberBoard++;
    }
    
    public void addCardAirport(String cardName, int buycost, int air1, int air2, int air3, int air4, int mortgage) {
        Card card = new AirportCard(cardName, buycost, air1, air2, air3, air4, mortgage);
        Cards.add(card);
        numberBoard++;
    }
    
    public void addCardHouse(String cardName, int buycost, int rent, int h1, int h2, int h3, int h4, int hotel, int mortgage, int hcost) {
        Card card = new HouseCard(cardName, buycost, rent, h1, h2, h3, h4, hotel, mortgage, hcost);
        Cards.add(card);
        numberBoard++;
    }
}

如何解决此问题?

首先,如果您希望尊重封装并使用访问者方法,则应将HouseCard属性设置为private

其次,记住分享所有相关的代码,这样我们可以更好地帮助您。我假设
Players.get(I).getSquare
在代码中返回
HouseCard
的实例

最后,如果
square
属性是
Card
的类型,则在调用
getCardName()
方法之前,需要对
HouseCard
进行强制转换

你最终会得到这样的结果:

HouseCard card = (HouseCard) Player.get(i).getSquare();
String cardName = card.getCardName();

您的问题是
getCardName()
方法未在
Card
类中定义。由于该变量看起来像是应用于所有子类的数据,因此我建议将其上移到父类
Card
类中

public abstract class Card {
  private String cardName;

  public Card(String cardName) {
     this.cardName = cardName;
  }

  public String getCardName() {
    return cardName;
  }

  //Other methods
}
然后,您的子类可以在实例化时调用
super()
方法来设置该值

public class HouseCard extends Card {
  public HouseCard(String cardName) {
    super(cardName);
  }
}
然后在
Card
对象上调用
getCardName()
方法不会有任何问题,因为您定义了
Card
父类中的内容。然后,您还可以在子类中调用
getCardName()
方法来获取此上下文中的值(或者如果您只想直接引用变量,可以使用
protected
关键字而不是
private


为了便于发布,我建议将代码复制/粘贴到文本框中,然后突出显示复制的代码,然后点击编辑器顶部的代码按钮(看起来像
{}
)。这将适当地将其隔开,以便放入代码框中。@TimHunter非常感谢Hanks!“这真的帮了我的忙。”卡莫拉:当然,伙计。希望您的项目的其余部分进展顺利!谢谢祝你有愉快的一天。@Kamora不知道我明白你的意思吗?如果一个变量可以应用于所有子类,那么它应该在父类中。如果它不适用于所有人,那么它应该在子类中。如果需要访问子类特有的变量,则需要使用fsimon向您展示的技术获取
Card
对象并将其转换为子类。您可以将
super()
方法视为调用父类的构造函数,这意味着您可以像常规构造函数一样通过它设置多个变量。在设置子类变量之前,确实需要调用
super()
类。@在尝试强制转换之前,您还可以使用
instanceof
关键字()检查
Card
对象是否是特定子类的实例。否则,您可以考虑在“代码>卡/<代码>对象中使用不同的卡类型作为变量,并确保在制作卡时设置。然后您只需要检查枚举是哪个值,就可以知道它应该被转换为什么。很抱歉,我不能提供更多的代码,但是播放器是。get(i)。getSquare()返回播放器所在的平方的整数。此外,我明白你的意思,我会看看我是否也能使用这个解决方案
public class HouseCard extends Card {
  public HouseCard(String cardName) {
    super(cardName);
  }
}
@Override
public String toString() {
  return getCardName() + " some other info specific to this class"; 
}