Невозможно вызвать метод из классов в HashSet - PullRequest
0 голосов
/ 28 апреля 2011

То, что я пытаюсь сделать, это суммировать значения воздействия в классе опасности

Например, он просмотрит список жителей, найдет опасность и получит от нее величину воздействия. Затем суммируйте общее воздействие всех опасностей и верните мне это значение.

Ниже у меня есть класс пещер , класс опасности и абстрактный класс обитателя .

При добавлении опасности в пещеру она становится обитателем HashSet. При попытке получить энергетические уровни с помощью метода getImpact () к нему нельзя получить доступ, так как он находится в Hazard, а не в Occupant.

У меня есть два других класса, которые также расширяют Occupant. Игрок и Item .

Я не могу найти способ сохранить опасность как класс Hazard при добавлении в HashSet, чтобы можно было использовать метод getImpact ().

Это также необходимо для обслуживания других классов Player и Item при добавлении в HashSet.


public class Cave {

HashSet<Occupant> occupants;
private double impact;

/**
 * Creat a new Cave instance with no occupants.
 */
public Cave() 
{
    occupants = new HashSet<Occupant>();
}

/**
 * Adds an occupant to a Cave if the occupant is not already there and
 * if cave currently has fewer than the maximum number of occupants.
 * @param occupant, the occupant to add
 * @return  true if successfully added
*/
public boolean addOccupant(Occupant occupant) {
    boolean validNewOccupant = occupant != null;
    boolean enoughRoom = occupants.size() < MAX_OCCUPANTS;
    if (validNewOccupant && enoughRoom) {
        validNewOccupant = occupants.add(occupant);
    }

    return validNewOccupant && enoughRoom;
}

/**
 * Gets the sum of the impact from all hazards in the cave
 * @returns hazardEnergyImpact
 */
public double getHazardEnergyImpacts(){
    double energyImpact = 0.0;
    for( Occupant occupant : occupants ){
        if(occupant.toString() == "!"){
            energyImpact += occupant.getImpact();
        }
    }
    return energyImpact;
}
}

public abstract class Occupant {

private Address address;
private String name;

/**
 * Construct an occupant for a known address & name.
 * @ param row, row of address  
 * @ param column, row of address.
 * @ param name, occupant's name
 */
public Occupant(Address address, String name) {
    this.address = address;
    this.name = name;
}

@Override
public String toString(){
    return "";
}
}

public class Hazard extends Occupant  {

private String longDescription;
private double impact;

/**
 * Construct a hazard with know attributes
 * @param row
 * @param column
 * @param name
 * @param longDescription
 * @param impact
 */
public Hazard(Address address, String name, String longDescription, double impact) {
    super(address, name);
    this.longDescription = longDescription;
    this.impact = impact;
}

@Override
public String toString(){
    return "!";
}

/**
 * gets impact amount
 * @returns impact
 */
public double getImpact(){
    return this.impact;
}
}

Ответы [ 4 ]

3 голосов
/ 28 апреля 2011

Другой вариант - добавить метод getImpact() в Occupant, например,

public double getImpact() {
    return 0.0;
}

, тогда как реализация @Override Hazard getImpact() просто вернет переменную экземпляра impactкак вы уже настроили.Затем ваш цикл упрощается до:

public double getHazardEnergyImpacts() {
    double energyImpact = 0.0;
    for( Occupant occupant : occupants ) {
        energyImpact += occupant.getImpact();
    }
    return energyImpact;
}

Если вам потребуется извлечь данные в соответствующую абстракцию интерфейса позже, хорошо, что современные IDE делают это проще.

1 голос
/ 28 апреля 2011

При итерации по вашему occupants вы можете проверить, является ли каждый элемент Hazard следующим образом:

for(Occupant occupant : occupants){
    if(occupant instanceof Hazard){
        Hazard hazard = (Hazard) occupant; // now it's safe to cast
        double impact = hazard.getImpact();
        // do what you want with impact
    }
}
0 голосов
/ 28 апреля 2011

Я бы использовал Шаблон посетителя здесь.

public interface Occupant {
  void interact(Player p);
}

public class Player {
  public void handleInteraction(Hazard hazard) {
    // add code here
  }
  public void handleInteraction(Person person) {
    // add code here
  }
}

public class Hazard implements Occupant {
  public void interact(Player p) {
    p.handleInteraction(this);
  }

  public double getImpact(){
    return this.impact;
  }
}
0 голосов
/ 28 апреля 2011

Джереми опередил меня.

Однако instanceof не всегда лучшее решение.В этом случае, однако, это исправление.

Я бы действительно рекомендовал использовать здесь интерфейсы для поведения вместо использования абстрактного класса.Однако, если вам нужно использовать абстрактный класс, более эффективный способ сделать это - просто создать абстрактные методы, которые вы хотите использовать в своих дочерних классах.Вам придется переопределить их все в каждом дочернем элементе, но вам не нужно применять их в каждом случае.

...