Aller au contenu principal

Packages et imports

Notions théoriques

Pourquoi les packages ?

Quand un projet grandit, on se retrouve avec des dizaines ou des centaines de classes. Les packages permettent d'organiser ces classes en dossiers logiques, comme on range des fichiers dans des dossiers sur son ordinateur.

Un package sert à :

  • Organiser le code par domaine fonctionnel
  • Éviter les conflits de noms (deux classes Personnage dans des packages différents coexistent sans problème)
  • Contrôler l'accès (visibilité package-private)

Convention de nommage des packages

Par convention, les noms de packages sont en minuscules et suivent la structure du nom de domaine inversé de l'organisation :

com.joliciel.rpg.personnages
├── com ← domaine de premier niveau
├── joliciel ← nom de l'organisation
├── rpg ← nom du projet
└── personnages ← sous-domaine fonctionnel

Pour un projet scolaire, on peut simplifier :

fr.bts.rpg.personnages
fr.bts.rpg.combat
fr.bts.rpg.inventaire

La déclaration package

La première instruction d'un fichier Java (avant les imports et la classe) doit être la déclaration du package :

package com.joliciel.rpg.personnages;

public class Personnage {
// ...
}

Structure des dossiers avec Maven

Dans un projet Maven (structure standard Java), les packages correspondent à des dossiers dans src/main/java/ :

src/
└── main/
└── java/
└── com/
└── joliciel/
└── rpg/
├── personnages/
│ ├── Personnage.java
│ ├── Guerrier.java
│ └── Mage.java
├── combat/
│ └── Combat.java
└── Main.java

IntelliJ crée automatiquement la structure de dossiers correcte quand vous créez un nouveau package.

Import explicite

Pour utiliser une classe d'un autre package, on doit l'importer avec import :

package com.joliciel.rpg.combat;

import com.joliciel.rpg.personnages.Personnage; // import explicite

public class Combat {
void simuler(Personnage attaquant, Personnage defenseur) {
// ...
}
}

Import avec wildcard

On peut importer toutes les classes d'un package avec * :

import com.joliciel.rpg.personnages.*; // importe Personnage, Guerrier, Mage...
info

L'import avec * n'importe pas les sous-packages. import com.joliciel.rpg.* n'importe pas com.joliciel.rpg.personnages.Personnage.

Classes dans le même package

Deux classes dans le même package n'ont pas besoin d'import pour se voir mutuellement :

package com.joliciel.rpg.personnages;

// Guerrier.java — dans le même package que Personnage.java
// Pas besoin d'importer Personnage !
public class Guerrier {
Personnage cible; // fonctionne sans import
}

Classes de la bibliothèque standard

Les classes du package java.lang (String, Math, System, Integer...) sont disponibles sans import. Toutes les autres nécessitent un import :

import java.util.List;
import java.util.ArrayList;
import java.util.Scanner;

Exemple pratique

// Fichier : src/main/java/com/joliciel/rpg/personnages/Personnage.java
package com.joliciel.rpg.personnages;

public class Personnage {
private String nom;
private int force;
private int pointsDeVie;

public Personnage(String nom, int force, int pointsDeVie) {
this.nom = nom;
this.force = force;
this.pointsDeVie = pointsDeVie;
}

public String getNom() { return nom; }
public int getForce() { return force; }
public int getPointsDeVie() { return pointsDeVie; }

public void afficher() {
System.out.println(nom + " (Force:" + force + ", PV:" + pointsDeVie + ")");
}
}

// Fichier : src/main/java/com/joliciel/rpg/combat/Combat.java
package com.joliciel.rpg.combat;

import com.joliciel.rpg.personnages.Personnage;

public class Combat {
public static void simuler(Personnage attaquant, Personnage defenseur) {
System.out.println(attaquant.getNom() + " attaque " + defenseur.getNom() + " !");
}
}

// Fichier : src/main/java/com/joliciel/rpg/Main.java
package com.joliciel.rpg;

import com.joliciel.rpg.personnages.Personnage;
import com.joliciel.rpg.combat.Combat;

public class Main {
public static void main(String[] args) {
Personnage hero = new Personnage("Aria", 18, 100);
Personnage ennemi = new Personnage("Golem", 12, 80);

hero.afficher();
ennemi.afficher();

Combat.simuler(hero, ennemi);
}
}

Test de mémorisation/compréhension


Où doit se trouver la déclaration `package` dans un fichier Java ?


Quelle est la convention de nommage des packages Java ?


Si la classe `Guerrier` est dans le même package que `Personnage`, a-t-on besoin d'un import ?


Que fait `import java.util.*;` ?


Quel package Java ne nécessite jamais d'import ?


Dans un projet Maven, dans quel dossier se trouvent les fichiers Java sources ?


TP pour réfléchir et résoudre des problèmes

Vous allez restructurer le projet RPG en packages logiques.

Étape 1 — Déclarer le package de Personnage

Ajoutez la déclaration de package com.joliciel.rpg.personnages en tête du fichier Personnage.java.


Bonne pratique - Toujours déclarer un package

Ne laissez pas vos classes dans le "package par défaut" (sans déclaration de package). C'est une mauvaise pratique qui rend le code non réutilisable et peut causer des conflits de noms. Même pour un petit projet, déclarez un package.

Étape 2 — Importer Personnage dans Main

Dans Main.java (package com.joliciel.rpg), importez la classe Personnage.


Bonne pratique - Préférer les imports explicites aux wildcards

Préférez import com.joliciel.rpg.personnages.Personnage à import com.joliciel.rpg.personnages.*. Les imports explicites rendent visible d'un coup d'œil quelles classes sont utilisées dans le fichier. IntelliJ les gère automatiquement.

Étape 3 — Créer la classe Combat dans son propre package

Créez une classe Combat dans le package com.joliciel.rpg.combat avec une méthode simuler.


Bonne pratique - Organiser par domaine fonctionnel

Organisez vos packages par domaine métier (personnages, combat, inventaire) plutôt que par type technique (modeles, services, utils). Une organisation par domaine facilite la navigation dans le code et permet de localiser rapidement tout ce qui concerne un sujet donné.

📌 Une solution