Проблема с циклической зависимостью Phaser 3

#javascript #typescript #phaser-framework #circular-dependency

#javascript #typescript #phaser-framework #циклическая зависимость

Вопрос:

Как решить циклическую зависимость в Phaser 3

Предыстория

Я создаю игру с помощью Phaser 3, TypeScript и Parcel. Я добавил несколько классов, которые реализуют некоторые интерфейсы, но интерфейсы импортируют и используют друг друга. Я начал использовать eslint с набором правил airbnb. Одно из правил, которые они реализуют import/no-cycle , но я чувствую, что моя игра нуждается в этом.

Пример кода

GameInterface.ts

 import { Scene } from 'phaser';
import PlayerInterface from '../../entities/player/PlayerInterface'; // circular

interface GameInterface extends Scene {
  player: PlayerInterface;
}

export default GameInterface;

  

PlayerInterface.ts

 import GameInterface from '../../scenes/game/GameInterface'; // circular

interface PlayerInterface extends Phaser.Physics.Arcade.Sprite {
  scene: GameInterface;
  speed: number;
}

export default PlayerInterface;
  

Вопрос

В «Игру» добавляется «Игрок», а у класса Player есть сцена. Поэтому они оба должны быть в интерфейсе. Поскольку это всего лишь файл типа, могу ли я игнорировать это правило? Или я могу сделать реструктуризацию cleaver?

Редактировать 1

Кроме того, вот ссылка на полное репозиторий.

Редактировать 2

Вот 2 класса, которые реализуют эти интерфейсы.

Game.ts

 class Game extends Scene implements GameInterface {
  player: PlayerInterface;

  constructor() {
    super({
      key: 'Game',
    });
  }

  preload(): void {
    /* preload code */
  }

  create(): void {
   /* create code */ 
  }
}
  

Player.ts

 class Player extends Phaser.Physics.Arcade.Sprite implements PlayerInterface {
  scene: GameInterface;

  constructor(scene: GameInterface) {
    super(scene, x, y, 'player');
    this.scene = scene;
    this.scene.add.existing(this);
    this.scene.physics.add.existing(this);
  }

  static preload(scene: GameInterface): void {
    /* preload */
  }
}
  

Как вы можете видеть, класс game создает игрока, но игроку также передается сцена при создании.

Комментарии:

1. можете ли вы попробовать поместить оба интерфейса в один и тот же файл?

2. Я не уверен, что ваша логика верна. Здесь вы описываете бесконечный рекурсивный объект javascript, который выглядит следующим образом: player = { scene: { player: { scene: { player: ... } } } } . Вы действительно манипулируете этим типом объекта?

3. Почему бы не объединить интерфейсы в файл?

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

Ответ №1:

первая из всех циклических зависимостей означает, что у вас есть два класса A amp; B :

  • Класс A использует класс B , поэтому A зависит от B
  • Класс B использует класс A , поэтому B от него тоже зависит A

В результате при инициализации обоих классов он запускает бесконечный цикл, потому что он хочет создать класс A на основе B, а класс хочет быть создан на основе класса A, хотя он пошел в цикл преимуществ.

введите описание изображения здесь

Так что просто отрежьте ненужную зависимость.

  1. Итак, в Game классе, похоже, вам не нужно было использовать PlayerInterface .
  2. А также вам не нужно было выходить из Scene Phaser.Physics.Arcade.Sprite ваших интерфейсов и в них. Потому что вы уже расширяете их в своих конкретных классах. Просто удалите их.

Комментарии:

1. Циклическая зависимость исходит только от моих интерфейсов. Я использую как player, так и game в каждом из классов. Я просто не показываю их здесь в коде, потому что это раздувает вопрос. Я протестирую удаление сцены и спрайта из интерфейса, но я чувствую, что раньше это давало мне ошибки.

2. К вашему сведению, удаление сцены / спрайта из расширения — это плохо. их интерфейс не представляет, что это такое, если я его удалю. Если я удалю его из класса, он не будет работать, потому что внутренний интерфейс реализован неправильно.

Ответ №2:

Поместите оба интерфейса в один файл. Это избавит вас от циклической загрузки файлов, что и сбивает вас с толку.

Комментарии:

1. Это не масштабируемое решение