2012-02-26 10 views
15

Estoy trabajando en un proyecto que implica una gran cantidad de interfaces y herencia, que están empezando a ser un poco complicado, y ahora me he encontrado con un problema.¿Usando 'esto' en el constructor base?

Tengo un estado de clase abstracto que toma en un objeto Juego como un argumento de constructor. En el constructor de mi clase Game, toma en estado. La idea es que al heredar de la clase de juego base abstracta, cuando se llama al constructor de la clase base, se le da un objeto de estado inicial. Sin embargo este objeto Estado toma en el mismo juego que va a crear en el código es el siguiente:.

public class PushGame : ManiaGame 
{ 
    public PushGame() : 
      base(GamePlatform.Windows, new PlayState(this), 60) 
    { 
    } 
} 

Sin embargo, esto no funciona. Solo puedo suponer porque la palabra clave 'this' no se puede utilizar hasta después de que el constructor haya comenzado a ejecutar. Tratar de usarlo en el constructor de su clase base no funciona, al parecer. Entonces, ¿cuál sería mi mejor solución para esto? Mi plan B es eliminar el argumento del estado del constructor de la clase Game y simplemente establecer el estado dentro del código del constructor después.

¿Hay una manera más fácil y menos intrusiva de hacer esto?

+1

No coloque los títulos con "C#" y tal. Para eso son las etiquetas. –

Respuesta

9

Es evidente que la clase ManiaGame siempre utiliza los objetos de tipo PlayState, para que pueda mover la creación a nivel ManiaGame:

public class PushGame : ManiaGame 
{ 
    public PushGame() : base() 
    { 
    } 

} 

public class ManiaGame 
{ 
    PlayState ps; 
    public ManiaGame() { 
     ps = new PlayState(this); 
    } 
} 

Si desea clases PlayState más concretos ..

public class PushGame : ManiaGame 
{ 
    public PushGame() : base() 
    { 
    } 
    protected override PlayState CreatePlayState() 
    { 
     return new PushGamePlayState(this); 
    } 
} 

public class ManiaGame 
{ 
    PlayState ps; 
    public ManiaGame() { 
      ps = CreatePlayState(); 
    } 
    protected virtual PlayState CreatePlayState() 
    { 
     return new PlayState(this); 
    } 
} 

public class PlayState 
{ 
    public PlayState(ManiaGame mg) {} 
} 


public class PushGamePlayState : PlayState 
{ 
    public PushGamePlayState(ManiaGame mg) : base(mg){} 
} 
+0

+1 y también destaca la codependencia entre ManiaGame y PlayState, por lo que los 2 objetos nunca se pueden referenciar "simultáneamente" en los respectivos constructores. – StuartLC

+1

Es importante mencionar que llamar a un método virtual desde dentro del ctor puede ser peligroso - http://stackoverflow.com/questions/119506/virtual-member-call-in-a-constructor – AlexD

0

Parece que 'esto' solo se puede usar para hacer referencia a otro constructor en ese contexto.

Es decir, se utiliza como una palabra clave de alcance antes de que se ejecuta el constructor:

: this("ParameterForAnotherConstructor") 

Pero no está disponible como referencia habitual a la instancia de clase,

: base(this) // Keyword this is not available in this context 

y, obviamente, no puede llamar a cualquier método de instancia, ya sea

: base(GetThis()) // Object reference is required 

Hay un desbordamiento de pila similares qu estion, Keyword 'this' (Me) is not available calling the base constructor con una solución similar a su sugerencia.

1

Si la implementación State utilizada depende de la clase concreta Game, luego crearía una nueva instancia del State dentro del constructor de la clase Game secundaria (PushGame) y acceda al State en la clase base a través de la propiedad abstract.

public class PushGame : ManiaGame 
{ 
    private readonly PlayState gamePlayState; 

    public PushGame() : base() 
    { 
     gamePlayState = new PlayState(this); 
    } 

    protected override State GamePlayState 
    { 
     get { return gamePlayState; } 
    } 
} 

public abstract class ManiaGame 
{ 
    protected abstract State GamePlayState { get; } 
} 

public class State 
{ 
    public State(ManiaGame mg) { } 
} 


public class PlayState : State 
{ 
    public PlayState(ManiaGame mg) : base(mg) { } 
} 
0

¿Su diseño de diferenciar entre un juego (por ejemplo backgammon) y un juego en curso (un juego de backgammon)? Si está intentando mezclar estos dos conceptos, le sugiero que los modele por separado. Por ejemplo, Backgammon y BackgammonContest.

Cuestiones relacionadas