2016-12-23 20 views
1

设计多态类尝试设计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 
} 

所以用户应该延伸GameStateAbsGameMechanicsGameMechanics应该有特定类型的GameStateDominoMechanics =>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) 

Error:(41, 11) type mismatch; found : A$A133.this.DominoMechanics required: A$A133.this.GameMechanics[A$A133.this.GameState] Note: A$A133.this.DominoStarting <: A$A133.this.GameState (and A$A133.this.DominoMechanics <: A$A133.this.AbsGameMechanics[A$A133.this.DominoStarting]), but trait GameMechanics is invariant in type T. You may wish to define T as +T instead. (SLS 4.5) internal(domino) ^

我做错了什么。什么?

+0

搜索“斯卡拉协变”,有很多关于这方面的问题。 –

回答

0

你的方法internal只接受GameMechanics[GameState],但你尝试在GameMechanics[DominoStarting]通过,这是不是因为GameMechanics[GameState]GameMechanicsT型不变的一个亚型。你可能想查找一些关于不变性和协变性的其他问题,因为有很多。

但我认为你的代码中的问题不一定是关于协方差或不变性。你不应该要求GameMechanics[GameState]。您已经定义T为具有要的GameState亚型......如果你接受任何形式的GameMechanics你应该做的是:

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

或者当你不关心的确切类型:

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