Предположим, у меня есть два класса:

class PlayerManagerParent {
   public function new(){
   }  
}

class GameManagerParent {
   public var playerManager:PlayerManagerParent();

   public function new(){
   }  
}

Который затем я подклассифицирую как

class PlayerManagerChild extends PlayerManagerParent {
   public function new(){
      super();
   }  

   public function someMethod(){
   }
}

class GameManagerChild extends GameManagerParent {

   public function new(){
      super();
      this.playerManager = new PlayerManagerChild();
   }  
}

Затем я создаю экземпляр GameManagerChild и хочу получить доступ к someMethod():

var gameManager:GameManagerChild = new GameManagerChild();
gameManager.playerManager.someMethod();

Чего я, конечно, не могу сделать, поскольку gameManager.playerManager - это тип playerManager:PlayerManagerParent, который не определяет someMethod(), а компилятор / проверка типов выдает мне ошибку.

Как я могу решить эту проблему без объявления someMethod() в родительском классе или установки типа playerManager на Dynamic (что было бы вариантом, но тогда я не могу перебирать повторяемые поля в {{X3} }, например)?

2
wildfireheart 26 Окт 2015 в 18:36

2 ответа

Лучший ответ

Для этого вы можете использовать ограниченный параметризованный тип:

class PlayerManagerParent {
   public function new(){
   }  
}

class GameManagerParent<T:PlayerManagerParent> {
   public var playerManager:T;

   public function new(){
   }  
}

При этом вы можете расширить его так:

class PlayerManagerChild extends PlayerManagerParent {
   public function new(){
      super();
   }  

   public function someMethod(){
   }
}

class GameManagerChild extends GameManagerParent<PlayerManagerChild> {

   public function new(){
      super();
      this.playerManager = new PlayerManagerChild();
   }  
}

Что позволяет вам сделать это:

var child = new GameManagerChild();
child.playerManager.someMethod();

Живой пример:
http://try.haxe.org/#21bfC

См. также:
http://haxe.org/manual/type-system-type-parameters.html

Совет: вы даже можете пометить его как @:generic, что может повысить производительность на некоторых платформах: http://haxe.org/manual/type-system-generic.html

4
Mark Knol 26 Окт 2015 в 17:00

Вероятно, вам следует использовать параметры типа, например:

class GameManagerParent<PM:PlayerManagerParent> {
     public var playerManager : PM;
}

class GameManagerChild 
extends GameManagerParent<PlayerManagerChild> {
     public function new() {
         playerManager = new PlayerManagerChild();
     }
}
3
clemos 26 Окт 2015 в 17:05