Bonjour,

Je me heurte à un problème d'héritage.

Voilà, je créée une application de style répertoire de personnes grâce à laquelle je souhaite afficher les attributs des Objets suivants :

  • Personne

  • Eleve extends Personne

  • Professeur extends Personne

  • Elu extends Personne


Bien sûr, la classe Personne détient tous les attributs qui sont communs aux classes filles, et les classes filles détiennent des attributs spécifiques. Mis à part un attribut nommé "instrument" qui est présent dans les classes filles Eleve et professeur et que j'ai décidé de mettre dans Personne (voir les constructeurs des classes filles plus bas dans ce message).


Je désire donc afficher ces objets dans une sorte de répertoire qui contiendra des champs issus de toutes les sous-classes (classes filles) de Personnes.

Pour préparer un jeu de données, j'ai créé plusieurs instances de chaque sous-classe de Personne dans le constructeur de la classe MainApp :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// The data as an observable list of Personne
private ObservableList<Personne> personnes = FXCollections.observableArrayList();
public ObservableList<Personne> getPersonnes() {return personnes;}
 
//CONSTRUCTEUR
public MainApp() {
	// Add some sample data
	personnes.add(new Elu("nom1", "prenom1", 35, 1, null, null, null, null, null, null, "PRESIDENT"));
	personnes.add(new Eleve("nom2", "prenom2", 42, 2, null, null, null, null, null, null, "BATTERIE"));
	personnes.add(new Professeur("nom3", "prenom3", 17, 2, null, null, null, null, null, null, "PIANO", null));
	personnes.add(new Elu("nom4", "prenom4", 8, 5, null, null, null, null, null, null, "TRESORIER"));
	personnes.add(new Eleve("nom5", "prenom5", 37, 4, null, null, null, null, null, null, "PIANO"));
	personnes.add(new Professeur("nom6", "prenom6", 29, 3, null, null, null, null, null, null, "BATTERIE", "SOLFEGE"));
}
Mon problème se situe dans l'assignation des champs de chaque objet aux colonnes du répertoire.

Cette assignation est décrite dans la méthode initialize() de la classe PersonneOverviewControleur que voici :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
// Initializes the controller class. This method is automatically called
// after the fxml file has been loaded.
@FXML
private void initialize() {
	// Initialize the personne table with the columns.
	nomColumn.setCellValueFactory(cellData -> cellData.getValue().nomProperty());
	prenomColumn.setCellValueFactory(cellData -> cellData.getValue().prenomproperty());
	instrumentColumn.setCellValueFactory(cellData -> cellData.getValue().instrumentProperty());
	fonctionColumn.setCellValueFactory(cellData -> cellData.getValue().fonctionProperty());
	matiereColumn.setCellValueFactory(cellData -> cellData.getValue().matiereproperty());
}
Ce qui se passe c'est qu'ayant créé un jeu de différentes sous classes de Personnes , lorsqu'il faut assigner un champs qui n'est pas présent dans la classe mère, je me retrouve avec une belle ClassCastException que voici !
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: saubens.ecole.adherents.model.Eleve cannot be cast to saubens.ecole.adherents.model.Elu
	at saubens.ecole.adherents.view.PersonneOverviewControleur.lambda$3(PersonneOverviewControleur.java:70)
Donc pour résumer, je pense que les différentes Personne issues du jeu de données sont traitées une par une comme un for afin d'en extraire les différents attributs que je souhaite assigner aux champs. Mais lorsque le programme arrive à l'assignation d'un champs spécifique à une classe fille (par exemple Elu) alors qu'il est en train de traiter un autre classe fille qui ne contient pas ce champs (par exemple Eleve), une erreur est générée.

Alors, je pense qu'une solution aurait été de tester l'objet issu du jeu de données avant de l'assigner à une colonne mais je ne peux pas tester car la méthode initialize() est appelée par le .fxml (enfin d'après ce que j'ai compris ...) et je n'ai pas trouvé comment je peux appeler dans un if l'objet qui est traité dans initialize() ...


Merci de bien vouloir m'aider !

Voici toutes mes classes :

package : model, classe : Personne.java :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package saubens.ecole.adherents.model;
 
import java.time.LocalDate;
 
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
 
public class Personne {
 
	//ATTRIBUTS
	private final StringProperty nom;
	private final StringProperty prenom;
	private final IntegerProperty age;
	private final IntegerProperty anciennete;
	private final StringProperty genre;
	private final ObjectProperty<LocalDate> anniversaire;
	private final StringProperty adresse;
	private final StringProperty email;
	private final StringProperty tel1;
	private final StringProperty tel2;
	private final StringProperty instrument;
 
 
	//CONSTRUCTEURS
	public Personne() {
		this(null, null, 0, 0, null, null, null, null, null, null, null);
	}
 
	public Personne(String nom,
			String prenom,
			Integer age,
			Integer anciennete,
			String genre,
			LocalDate anniversaire,
			String adresse,
			String email,
			String tel1,
			String tel2,
			String instrument) {
		this.nom = new SimpleStringProperty(nom);
		this.prenom = new SimpleStringProperty(prenom);
		this.age = new SimpleIntegerProperty(age);
		this.anciennete = new SimpleIntegerProperty(anciennete);
		this.genre = new SimpleStringProperty(genre);
			//Attention, il faudra peut-être une classe utilitaire de conversion des jour (int), mois(int) et année(int)
			// -> LocalDate.of(int jour, int mois, int année))
		this.anniversaire = new SimpleObjectProperty<LocalDate>(anniversaire);
		this.adresse = new SimpleStringProperty(adresse);
		this.email = new SimpleStringProperty(email);
		this.tel1 = new SimpleStringProperty(tel1);
		this.tel2 = new SimpleStringProperty(tel2);
		this.instrument = new SimpleStringProperty(instrument);
	}
 
	//ACCESSEURS
	public String getNom() {return nom.get();}
	public void setNom(String nom) {this.nom.set(nom);}
	public StringProperty nomProperty() {return nom;}
 
	public String getPrenom() {return prenom.get();}
	public void setPrenom(String prenom) {this.prenom.set(prenom);}
	public StringProperty prenomproperty() {return prenom;}
 
	public int getAge() {return age.get();}
	public void setAge(int age) {this.age.set(age);}
	public IntegerProperty ageProperty() {return age;}
 
	public int getAnciennete() {return anciennete.get();}
	public void setAnciennete(int anciennete) {this.anciennete.set(anciennete);}
	public IntegerProperty ancienneteProperty() {return anciennete;}
 
	public String getGenre() {return genre.get();}
	public void setGenre(String genre) {this.genre.set(genre);}
	public StringProperty genreProperty() {return genre;}
 
	public LocalDate getAnniversaire() {return anniversaire.get();}
	public void setAnniversaire(LocalDate anniversaire) {this.anniversaire.set(anniversaire);}
	public ObjectProperty<LocalDate> anniversaireProperty() {return anniversaire;}
 
	public String getAdresse() {return adresse.get();}
	public void setAdresse(String adresse) {this.adresse.set(adresse);}
	public StringProperty adresseProperty() {return adresse;}
 
	public String getEmail() {return email.get();}
	public void setEmail(String email) {this.email.set(email);}
	public StringProperty emailProperty() {return email;}
 
	public String getTel1() {return tel1.get();}
	public void setTel1(String tel) {this.tel1.set(tel);}
	public StringProperty tel1Property() {return tel1;}
 
	public String getTel2() {return tel2.get();}
	public void setTel2(String tel) {this.tel2.set(tel);}
	public StringProperty tel2Property() {return tel2;}
 
	public String getInstrument() {return instrument.get();}
	public void setInstrument(String instrument) {this.instrument.set(instrument);}
	public StringProperty instrumentProperty() {return instrument;}
 
	//METHODES
 
}
package : model, classe : Eleve.java :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package saubens.ecole.adherents.model;
 
import java.time.LocalDate;
 
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
 
public class Eleve extends Personne{
 
	//ATTRIBUTS
	protected final StringProperty instrument;
 
	//CONSTRUCTEURS
	public Eleve(String nom, String prenom, Integer age, Integer anciennete, String genre, LocalDate anniversaire,
			String adresse, String email, String tel1, String tel2, String instrument) {
		super(nom, prenom, age, anciennete, genre, anniversaire, adresse, email, tel1, tel2, instrument);
		this.instrument = new SimpleStringProperty(instrument);
	}
 
	//ACCESSEURS
	public String getInstrument() {return instrument.get();}
	public void setInstrument(String instrument) {this.instrument.set(instrument);}
	public StringProperty instrumentProperty() {return instrument;}
}
package : model, classe : Elu.java :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package saubens.ecole.adherents.model;
 
import java.time.LocalDate;
 
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
 
public class Elu extends Personne{
 
	//ATTRIBUTS
	private final StringProperty fonction;
 
	//CONSTRUCTEURS
	public Elu(String nom, String prenom, Integer age, Integer anciennete, String genre, LocalDate anniversaire,
			String adresse, String email, String tel1, String tel2, String fonction) {
		super(nom, prenom, age, anciennete, genre, anniversaire, adresse, email, tel1, tel2, null);
		this.fonction = new SimpleStringProperty(fonction);
	}
 
	//ACCESSEURS
	public String getFonction() {return fonction.get();}
	public void setFonction(String fonction) {this.fonction.set(fonction);}
	public StringProperty fonctionProperty() {return fonction;}
}
package : model, classe : Professeur.java :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package saubens.ecole.adherents.model;
 
import java.time.LocalDate;
 
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
 
public class Professeur extends Personne{
 
	//ATTRIBUTS
	private final StringProperty instrument;
	private final StringProperty matiere;
 
	//CONSTRUCTEURS
	public Professeur(String nom, String prenom, Integer age, Integer anciennete, String genre, LocalDate anniversaire,
			String adresse, String email, String tel1, String tel2, String instrument, String matiere) {
		super(nom, prenom, age, anciennete, genre, anniversaire, adresse, email, tel1, tel2, instrument);
		this.instrument = new SimpleStringProperty(instrument);
		this.matiere = new SimpleStringProperty(matiere);
	}
 
	//ACCESSEURS
	public String getInstrument() {return instrument.get();}
	public void setInstrument(String instrument) {this.instrument.set(instrument);}
	public StringProperty instrumentProperty() {return instrument;}
 
	public String getMatiere() {return matiere.get();}
	public void setMatiere(String matiere) {this.matiere.set(matiere);}
	public StringProperty matiereproperty() {return matiere;}
}
package : view, classe : PersonneOverviewControleur.java :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package saubens.ecole.adherents.view;
 
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import saubens.ecole.adherents.MainApp;
import saubens.ecole.adherents.model.Elu;
import saubens.ecole.adherents.model.Personne;
import saubens.ecole.adherents.model.Professeur;
 
public class PersonneOverviewControleur {
	@FXML
	private TableView<Personne> personneTable;
	@FXML
	private TableColumn<Personne, String> nomColumn;
	@FXML
	private TableColumn<Personne, String> prenomColumn;
	@FXML
	private TableColumn<Personne, String> instrumentColumn;
	@FXML
	private TableColumn<Elu, String> fonctionColumn;
	@FXML
	private TableColumn<Professeur, String> matiereColumn;
 
	@FXML
	private Label nomLabel;
	@FXML
	private Label prenomLabel;
	@FXML
	private Label adresseLabel;
	@FXML
	private Label tel1Label;
	@FXML
	private Label tel2Label;
	@FXML
	private Label emailLabel;
	@FXML
	private Label genreLabel;
	@FXML
	private Label ageLabel;
	@FXML
	private Label ancienneteLabel;
	@FXML
	private Label anniversaireLabel;
	@FXML
	private Label instrumentLabel;
	@FXML
	private Label fonctionLabel;
	@FXML
	private Label matiereLabel;
	@FXML
	private Label distanceLabel;
 
	// Reference to the main application.
	private MainApp mainApp;
 
	// The constructor is called before the initialize() method.
	public PersonneOverviewControleur() {}
 
	// Initializes the controller class. This method is automatically called
	// after the fxml file has been loaded.
	@FXML
	private void initialize() {
		// Initialize the personne table with the columns.
		nomColumn.setCellValueFactory(cellData -> cellData.getValue().nomProperty());
		prenomColumn.setCellValueFactory(cellData -> cellData.getValue().prenomproperty());
		instrumentColumn.setCellValueFactory(cellData -> cellData.getValue().instrumentProperty());
		fonctionColumn.setCellValueFactory(cellData -> cellData.getValue().fonctionProperty());
		matiereColumn.setCellValueFactory(cellData -> cellData.getValue().matiereproperty());
	}
 
	// Is called by the main application to give a reference back to itself.
	public void setMainApp(MainApp mainApp) {
		this.mainApp = mainApp;
 
		// Add observable list data to the table
		personneTable.setItems(mainApp.getPersonnes());
	}
}
package : view, classe : AdherentsOverview.fxml
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?xml version="1.0" encoding="UTF-8"?>
 
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.Pane?>
 
<AnchorPane prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.72" xmlns:fx="http://javafx.com/fxml/1" fx:controller="saubens.ecole.adherents.view.PersonneOverviewControleur">
   <children>
      <SplitPane dividerPositions="0.3182957393483709" layoutX="87.0" layoutY="193.0" prefHeight="600.0" prefWidth="800.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
        <items>
          <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
               <children>
                  <Pane layoutX="57.0" layoutY="33.0" prefHeight="90.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
                     <children>
                        <CheckBox layoutX="9.0" layoutY="9.0" mnemonicParsing="false" text="Eleves" />
                        <CheckBox layoutX="9.0" layoutY="36.0" mnemonicParsing="false" text="Professeurs" />
                        <CheckBox layoutX="9.0" layoutY="66.0" mnemonicParsing="false" text="Bureau" />
                     </children>
                  </Pane>
                  <TableView fx:id="personneTable" layoutX="17.0" layoutY="208.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="90.0">
                    <columns>
                      <TableColumn fx:id="nomColumn" prefWidth="75.0" text="Nom" />
                      <TableColumn fx:id="prenomColumn" prefWidth="75.0" text="Prenom" />
                        <TableColumn fx:id="instrumentColumn" prefWidth="90.0" text="Instrument" />
                        <TableColumn fx:id="fonctionColumn" prefWidth="75.0" text="Fonction" />
                        <TableColumn fx:id="matiereColumn" prefWidth="75.0" text="Matière" />
                    </columns>
                  </TableView>
               </children>
            </AnchorPane>
          <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" />
        </items>
      </SplitPane>
   </children>
</AnchorPane>
package : view, classe : RootLayout.fxml
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?xml version="1.0" encoding="UTF-8"?>
 
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.layout.BorderPane?>
 
 
<BorderPane prefHeight="700.0" prefWidth="800.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.72">
   <top>
      <MenuBar BorderPane.alignment="CENTER">
        <menus>
          <Menu mnemonicParsing="false" text="File">
            <items>
              <MenuItem mnemonicParsing="false" text="Close" />
            </items>
          </Menu>
          <Menu mnemonicParsing="false" text="Edit">
            <items>
              <MenuItem mnemonicParsing="false" text="Delete" />
            </items>
          </Menu>
          <Menu mnemonicParsing="false" text="Help">
            <items>
              <MenuItem mnemonicParsing="false" text="About" />
            </items>
          </Menu>
        </menus>
      </MenuBar>
   </top>
</BorderPane>
classe : MainApp.java
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package saubens.ecole.adherents;
 
import java.io.IOException;
 
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import saubens.ecole.adherents.model.Eleve;
import saubens.ecole.adherents.model.Elu;
import saubens.ecole.adherents.model.Personne;
import saubens.ecole.adherents.model.Professeur;
import saubens.ecole.adherents.view.PersonneOverviewControleur;
 
public class MainApp extends Application {
 
	private Stage primaryStage;
	private BorderPane rootLayout;
 
 
	// The data as an observable list of Personne
	private ObservableList<Personne> personnes = FXCollections.observableArrayList();
	public ObservableList<Personne> getPersonnes() {return personnes;}
 
	//CONSTRUCTEUR
	public MainApp() {
		// Add some sample data
		personnes.add(new Elu("nom1", "prenom1", 35, 1, null, null, null, null, null, null, "PRESIDENT"));
		personnes.add(new Eleve("nom2", "prenom2", 42, 2, null, null, null, null, null, null, "BATTERIE"));
		personnes.add(new Professeur("nom3", "prenom3", 17, 2, null, null, null, null, null, null, "PIANO", null));
		personnes.add(new Elu("nom4", "prenom4", 8, 5, null, null, null, null, null, null, "TRESORIER"));
		personnes.add(new Eleve("nom5", "prenom5", 37, 4, null, null, null, null, null, null, "PIANO"));
		personnes.add(new Professeur("nom6", "prenom6", 29, 3, null, null, null, null, null, null, "BATTERIE", "SOLFEGE"));
	}
 
	@Override
	public void start(Stage primaryStage) {
		this.primaryStage = primaryStage;
		this.primaryStage.setTitle("Ecole de musique de Saubens");
 
		initRootLayout();
 
		showAdherentsOverview();
	}
 
	// Initializes the root layout.
	public void initRootLayout() {
		try {
			// Load root layout from fxml file.
			FXMLLoader loader = new FXMLLoader();
			loader.setLocation(MainApp.class.getResource("view/RootLayout.fxml"));
 
			rootLayout = (BorderPane) loader.load();
 
			// Show the scene containing the root layout.
			Scene scene = new Scene(rootLayout);
			primaryStage.setScene(scene);
			primaryStage.show();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
 
	// Shows the adherents overview inside the root layout.
	public void showAdherentsOverview() {
		try {
			// Load adherents overview.
			FXMLLoader loader = new FXMLLoader();
			loader.setLocation(MainApp.class.getResource("view/AdherentsOverview.fxml"));
			AnchorPane adherentsOverview = (AnchorPane) loader.load();
 
			// Set adherents overview into the center of root layout.
			rootLayout.setCenter(adherentsOverview);
 
			 // Give the controller access to the main app.
			PersonneOverviewControleur controleur = loader.getController();
			controleur.setMainApp(this);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
 
	// Returns the main stage.
	public Stage getPrimaryStage() {
		return primaryStage;
	}
 
	public static void main(String[] args) {
		launch(args);
	}
}