/ Polimorfismo da família em Scala - scala, polimorfismo

Polimorfismo familiar em Scala - scala, polimorfismo

Qual é o atual padrão recomendado para o polimorfismo familiar em Scala?

Ao experimentar maneiras de modelar jogos, essa solução surgiu recentemente:

trait Game[G <: Game[G]] {

type PLAYER <: Player[G]
type STATE <: State[G]

def players(): Set[G#PLAYER]

def startState(): G#STATE
}

trait Player[G <: Game[G]]

trait State[G <: Game[G]] {
def player(): G#PLAYER
}

Um jogo específico (poker neste exemplo) pode ser expresso em termos de características como:

class Poker() extends Game[Poker] {

type PLAYER = PokerPlayer
type STATE = PokerState

val p1 = new PokerPlayer()

def players() = Set(p1)

def startState(): PokerState = ...
}

class PokerPlayer() extends Player[Poker]

class PokerState() extends State[Poker] {
def player(): PokerPlayer = ...
}

Eu tenho várias perguntas sobre essa configuração:

  1. Como é Game[G <: Game[G]] pronunciado em inglês? Quais são os nomes das funções que G e Game está jogando nesta situação? (Significado especificamente nesse relacionamento "recursivo".)

  2. Esta é uma implementação razoável de "famíliapolimorfismo "? Em um nível alto, meu entendimento é que isso significa que o Jogo e seu JOGADOR e ESTADO devem variar como uma" família ". As opiniões sobre o polimorfismo familiar em Scala, que eu já vi em outros lugares, diferem substancialmente, e não estou claro sobre as diferentes vantagens e desvantagens:

  3. Discussões sobre abordagens do polimorfismo familiar envolvendo classes de tipos, macros, polimorfismo limitado a f ou qualquer outra coisa são bem-vindas.

Respostas:

2 para resposta № 1

Eu questionaria a necessidade de definir as classes "fora" da característica. Os tipos Player e State já dependem do jogo, então você não precisa restringi-lo ainda mais.

trait Game {
type Player
type State <: StateLike

trait StateLike {
def player: Player
}

def startState: State
}

class Poker extends Game {
class Player
class State extends StateLike { ... }
val startState = new State
}

Você pode usar o padrão de bolo para separar partes diferentes em diferentes características / arquivos, se desejar.

trait PokerPlayer extends Game {
class Player
}
trait PokerState extends Game with PokerPlayer {
class State extends StateLike { ... }
}
class Poker extends Game with PokerPlayer with PokerState {
val startState = ...
}