代码之家  ›  专栏  ›  技术社区  ›  zella

如何使用泛型设计多态类

  •  1
  • zella  · 技术社区  · 9 年前

    我试图设计具有通用多态性的api

    trait GameState {
      def doIt(): Unit
    }
    
    trait GameMechanics[T <: GameState] {
      def stateHolder: StateHolder[T]
    }
    
    abstract class AbsGameMechanics[T <: GameState](sh: StateHolder[T]) extends GameMechanics[T] {
      override def stateHolder: StateHolder[T] = sh
    }
    
    class StateHolder[T <: GameState](var state: T) {
      def get: T = state
      def set(_state: T): Unit = state = _state
    }
    

    因此,用户应该扩展 GameState AbsGameMechanics . GameMechanics 应具有特定类型的 游戏状态 , DominoMechanics => DominoGameState

    用户介绍新游戏:

    class DominoGameState extends GameState {
      override def doIt(): Unit = println("domino working!")
    }
    
    class DominoMechanics(sh: StateHolder[DominoGameState]) extends AbsGameMechanics[DominoGameState](sh)
    
    val domino = new DominoMechanics(new StateHolder[DominoGameState](new DominoGameState))
    

    在我的系统中,我应该对状态进行多态调用

    def internal(gm: GameMechanics[GameState]): Unit = {
      gm.stateHolder.get.doIt()
    }
    

    这不是编译,我不明白它是什么意思:

    internal(domino)
    

    错误:(41,11)类型不匹配;找到:A$A133.this.DominoMechanics 必需:A$A133.this.GameMechnics[A$A113.this.GameState]注: 这是133美元。主导<这是133美元。游戏状态(和 这是133美元。多米诺力学<: A$A133.this.AbsGameMechanics[A$A113.this.DominoStarting]),但特征 游戏机制在类型T中是不变的。您可能希望将T定义为+T 相反(SLS 4.5)内部(多米诺) ^

    我做错了什么。什么

    1 回复  |  直到 9 年前
        1
  •  0
  •   Jasper-M    9 年前

    你的方法 internal 只接受 GameMechanics[GameState] ,但你试图通过 GameMechanics[DominoStarting] ,它不是 游戏力学〔游戏状态〕 因为 GameMechanics 在类型上是不变的 T 你可能想查找一些关于不变性和协方差的其他问题,因为有很多。

    但我认为代码中的问题不一定是协方差或不变性。你不应该要求 游戏力学〔游戏状态〕 .您已经定义了 T 因为必须是 GameState …如果您接受任何类型的 游戏机制 是这样的吗

    def internal[S <: GameState](gm: GameMechanics[S]): Unit = {
      gm.stateHolder.get.doIt()
    }
    

    或者当您不关心确切类型时:

    def internal(gm: GameMechanics[_ <: GameState]): Unit = {
      gm.stateHolder.get.doIt()
    }
    
    推荐文章