Как реализовать шаблон Visitor для подтипов абстрактного класса или интерфейса? - PullRequest
0 голосов
/ 03 марта 2019

У меня есть эта конкретная проблема, которую я не мог решить с другими вопросами.Я пытаюсь реализовать посетителя для игры, посетитель класса Attack, и он должен искать в матрице ячейки, которые могут содержать Characters, тогда, если персонаж является врагом, а не другом, наносит уронit.

У меня возникли проблемы не с использованием InstanceOf для посещения персонажа, так как это нарушает принцип Open-Closed.Вот мой код:

Интерфейс посетителя

public interface Visitor {
    public void visit(GroundCell c);
    public void visit(MountainCell c);
    public void visit(BuildingCell c);
    public void visit(WaterCell c);
    public void visit(Foe f);
    public void visit(Friend f);}

Абстрактный класс атаки

public abstract class Attack implements Visitor {

}

Атака бетонаclass

public class TankAttack extends Attack{

...

@Override
public void visit(GroundCell c) {
    //here, i'd like to call  c.getCharacter.accept(this) 
}

Но я получаю ошибку, которая говорит Я должен сначала реализовать Visit (Символ c) , когда он мне нужен только для его подклассов.

Что я должен делать в классе TankAttack, чтобы посещать подклассы Друг или Враг персонажа и не нарушать дизайн с помощью InstanceOf?

Редактировать для пояснения: Друг и враг являются подклассами персонажа.

Ответы [ 2 ]

0 голосов
/ 03 марта 2019

Я решил это в нерабочее время.Эта проблема была вызвана не ошибочной реализацией шаблона Visitor, а тем, что суперкласс называется Character, так же как java.lang.Character.Остерегайтесь перезаписывать этот класс при программировании Java-игры.

0 голосов
/ 03 марта 2019

Посетитель не работает таким образом.

Все классы, объявленные здесь как параметры, являются посещаемыми классами:

public void visit(GroundCell c);
public void visit(MountainCell c);
public void visit(BuildingCell c);
public void visit(WaterCell c);
public void visit(Foe f);
public void visit(Friend f);}

Все они должны определять метод accept(Visitor visitor), который означает «Я принимаю визит посетителя».
Внутри них мы вызываем: visitor.visit(this), чтобы эффективно выполнить посещение с ожидаемой перегрузкой (двойная отправка).

Таким образом вы можете написать:

Attack attack = new TankAttack(); // visitor
Visited visitedOne = new GroundCell(); // visited one
Visited visitedTwo = new MountainCell(); // visited two

// accept the visitor and perform the double dispatch to invoke the specific method
visitedOne.accept(attack); 
visitedTwo.accept(attack); 

Или, в более общем случае, вы предоставляете метод с базовым типом посетителя в качестве параметра, например:

public void attack(Visited visited, Attack attack){
     visited.accept(attack); // no need instance of
}

Ииспользуйте это:

attack(new GroundCell(), attack); 
attack(new MoutainCell(), attack); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...