2016-11-22 1 views
0

Je suis en train de programmer un jeu (à un niveau très basique) pour un projet d'école en Java en utilisant BlueJ, et j'essaie de séparer un constructeur, contenant beaucoup d'informations, en deux ou trois constructeurs. Le code initial, avant mes changements se présente comme suit:Plusieurs constructeurs en Java

public class Game 

//fields omitted.. 
{ 
    public Game() //initialise game 
    { 
     createRooms(); 
    } 

    private void createRooms() // initialise rooms and exists and set start room. 
    { 
     Room bedRoom, kitchen; 

     bedRoom = new Room("in the bedroom"); 
     kitchen = new Room("in the kitchen"); 

     bedRoom.setExit("north", kitchen); 
     kitchen.setExit("south", bedRoom); 

     player = new Player(kitchen); 
    } 


    //Now, I want to seperate the contructor initialising the exits from the rest. 
    //I do so, by copying this to a new constructor below the createRooms constructor: 
    //initial code omitted.. 
    private void createRooms() // initialise rooms 
    { 
     Room bedRoom, kitchen; 

     bedRoom = new Room("in the bedroom"); 
     kitchen = new Room("in the kitchen"); 
    } 

    private void createExits() // initialise room exits and set start room. 
    { 
     Room bedRoom, kitchen; 

     bedRoom.setExit("north", kitchen); 
     kitchen.setExit("south", bedRoom); 

     player = new Player(kitchen); 
    } 
} 

Quand je compile, je reçois le message d'erreur dans le nouveau constructeur: « peut-être pas la variable BedRoom ont été initialisées ». Je ne comprends pas, puisque la variable a été initialisée dans le constructeur précédent. Cela peut-il être résolu à partir des informations et du code fournis ci-dessus? Merci d'avance!

BR Le débutant.

+5

Votre constructeur est une ligne. Comment pouvez-vous vouloir qu'il soit plus court? –

+1

Chacune de vos fonctions a une variable distincte, complètement indépendante. Vous voulez un champ dans la classe. – SLaks

+0

Vous n'avez même pas un vrai constructeur qui a des paramètres. Comment voulez-vous que ce soit plus court? – Grunzwanzling

Répondre

1

Dans votre code, bedRoom est une variable locale n'est pas un attribut, vous devez donc lui affecter une valeur lorsque vous le déclarez. Actuellement, il n'est pas initialisé et il ne sera même pas compilé, car s'il le faisait, il déclencherait un NullPointerException dès que votre code serait exécuté.

Si vous souhaitez initialiser les variables à l'intérieur du constructeur afin qu'ils puissent être vus partout, les déclarer en dehors comme attributs:

public class Game { 
    Room bedRoom; 
    Room kitchen; 
} 

Et supprimer ces lignes des autres méthodes:

Room bedRoom, kitchen; 
+0

Non; il n'est pas initialisé et donnera une erreur de compilation. – SLaks

+0

@SLaks droite, j'ai reformulé ma réponse. –

1

Les constructeurs sont supposés définir des valeurs pour chaque variable membre final (qui n'est pas directement initialisée lors de la déclaration). Donc ce que vous voulez n'est pas possible.

Vous pouvez supprimer le mot-clé final de certaines variables membres, mais ils peuvent être null ce qui est un problème assez souvent.

Si vous problème est que le constructeur a de nombreux paramètres, il y a (au moins) 2 approches communes:

  1. diviser les responsabilités de votre classe.
    Très probablement, votre classe en fait beaucoup et vous pourriez mettre une partie du code dans des classes séparées. Il y a de fortes chances pour que vous finissiez avec un tas de classes que vous utilisez en séquence de sorte que chaque classe comporte très peu de paramètres.

  2. utiliser le modèle Builder
    Avec le modèle de constructeur vous créez une catégorie distincte Builder où vous avez une méthode setter pour chaque paramètre du constructeur. Ces méthodes setter renvoient généralement this (l'instance de Builder en cours) afin que les appels puissent être chaînés. comme celui-ci

    MyClass theObject = new MyClassBuilder().withA("the A").withB("the B") /*... */ .withZ("the Z").build();

    La méthode build() vérifie si toutes les propriétés sont données et appelle le constructeur avec les lots de paramètres.

0

Variables bedRoom et kitchen ont une portée locale, ils n'existent pas en dehors des méthodes. Vous devez les déclarer en tant que membres de la classe.Et player ainsi.

Maintenant, vous devriez y réfléchir à deux fois lorsque vous mettez du code d'initialisation de membre de classe dans une méthode privée. Pourquoi? Parce que cette méthode peut être appelée après la construction, et cela va réinitialiser vos variables membres! La seule raison que je pourrais penser est que vous avez beaucoup de variables de membre, et le constructeur devient vraiment long.

class Game { 
    private Room bedRoom; 
    private Room kitchen; 
    private Player player; 

    public Game() { 
     // And you should initialize class members directly in the 
     // constructor. Most of the time. 
     bedRoom = new Room("in the bedroom"); 
     kitchen = new Room("in the kitchen"); 
     player = new Player(kitchen); 

     connectRooms(); 
    } 

    private void connectRooms() { 
     bedRoom.setExit("north", kitchen); 
     kitchen.setExit("south", bedRoom); 
    } 
}