@ColdSpirit

Как нормально пробросить данные в дочерние классы, используя ООП?

Доброе время суток! Пытаюсь сделать ИИ по совести, чтобы и ООП был, и универсальный, но не получается. Тупо C# не позволяет мне сделать это даже с генериками. Цель - пробросить в реализацию интерфейса IBotBehaviour кастомную информацию, нужную лишь для данного поведения. Хотелось бы пробросить ее через конструктор или метод. Но так, чтобы ее было обязательно пробрасывать.

Вот пример интерфейсов и реализаций:
IBotBehaviour - интерфейс поведения, который должен обязывать передавать ему информацию.
IBot - использует IBotBehaviour.
IdleBehaviour - ничего не делает, следовательно инфа ему никакая не нужна.
FollowBehaviour - требует 2 аргумента типа Positionу
BotTest - использует попеременно разные поведения и пробрасывает в них совершенно разные параметры.

Пример кода
public interface IBotBehaviour
{
    void Process();
    void Setup(); // ?
}

public interface IBot
{
    void SetBehaviour(IBotBehaviour behaviour);
}

public class IdleBehaviour : IBotBehaviour
{
    public void Process()
    {
        // wait 1s
    }

    public void Setup()
    {
    }
}

public class FollowBehaviour : IBotBehaviour
{
    Position myPosition;
    Position targetPosition;

    public void Process()
    {
        // move my pos to target pos
    }

    public void Setup(Position myPosition, Position targetPosition)
    {
        this.myPosition = myPosition;
        this.targetPosition = targetPosition;
    }
}

public class BotTest : IBot
{
    protected IBotBehaviour currentBehaviour;

    public void SetBehaviour(IBotBehaviour behaviour)
    {
        currentBehaviour = behaviour;
    }

    // call currentBehaviour.Process() in game cycle
}

  • Вопрос задан
  • 267 просмотров
Решения вопроса 3
Griboks
@Griboks Куратор тега C#
Интерфейс позволяет задать сигнатуру методу. Следовательно, аргументы можно прописать в самом интерфейсе.
Ответ написан
Простой, но немного измененый вариант
public interface IBotBehaviour
{
    void Process();
}

public interface IBot
{
    void SetBehaviour(IBotBehaviour behaviour);
}

public class IdleBehaviour : IBotBehaviour
{
    public void Process()
    {
        // wait 1s
    }
}

public class FollowBehaviour : IBotBehaviour
{

    public FollowBehaviour(Position myPosition, Position targetPosition)
    {

    }


    public void Process()
    {
        // move my pos to target pos
    }
}


// new BotTest().SetBehaviour(new FollowBehaviour(myPosition, targetPosition))
public class BotTest : IBot
{
    protected IBotBehaviour currentBehaviour;

    public void SetBehaviour(IBotBehaviour behaviour)
    {
        this.currentBehaviour = behaviour;
    }

    // call currentBehaviour.Process() in game cycle
}

Пример использования
new BotTest().SetBehaviour(new FollowBehaviour(myPosition, targetPosition))
Более сложный, но храняем ваши интерфейсы
public interface IBotState
{

}

public interface IBotBehaviour
{
    void Process();
    void Setup(IBotState state);
}

public interface IBotBehaviour<TState>
    where TState : IBotState
{
    void Setup(TState state);
}

public interface IBot
{
    void SetBehaviour(IBotBehaviour behaviour);
}

public class IdleBehaviour : IBotBehaviour
{
    public void Process()
    {
        // wait 1s
    }

    public void Setup(IBotState state)
    {

    }
}

public class FollowState : IBotState
{
    public Position myPosition;
    public Position targetPosition;
}

public class FollowBehaviour : IBotBehaviour<FollowState>
{
    Position myPosition;
    Position targetPosition;

    public void Process()
    {
        // move my pos to target pos
    }

    public void Setup(IBotState state)
    {
        this.Setup((FollowState)state);
    }

    public void Setup(FollowState state)
    {
        this.myPosition = state.myPosition;
        this.targetPosition = state.targetPosition;
    }
}

public class BotTest : IBot
{
    protected IBotBehaviour currentBehaviour;

    public void SetBehaviour(IBotBehaviour behaviour)
    {
        currentBehaviour = behaviour;
    }

    // call currentBehaviour.Process() in game cycle
}
Ответ написан
@ColdSpirit Автор вопроса
Сделал в итоге по такому принципу: все нужные данные для поведений содержит бот в открытом доступе, а поведения уже забирают их, кому что нужно:
public interface IBotBehaviour
{
    void Setup(BotBase bot);
    void Process();
}
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы