Forum Programmation.java dériver une classe conteneur de données de classe dérivée

Posté par  .
Étiquettes : aucune
0
30
mai
2007
Bonjour,

Je travaille sur la création d'un logiciel de modéilisation moléculaire appliqué à la théorie de Huckel en JAVA.Je

résume mon affaire
Actuellement un objet de classe Molecule est un un conteneur d'objtets d'Atomes Huckel et de Liaisons Huckel .

En gros :
public class Molecule {
private ArrayList lstAtom // liste d'atomes
private ArrayList lstBond // liste de liaisons
private int charge // charge de la molécule

/*** créer un atom d'un type Enum atomType à un poin donné ****/
public Atom createAtom (AtomType type, Point2D p) {...}

/** lier deux atomes . type de liaison = 1 ou 2 ou 3 (simple, double triple)
public void link (Atom a1, Atom a2, int type) {...}


public void rotate () {................}
public List getAtoms () {............}
public List getBonds () {............}

...........
}


Ma classe Atom et ma Class Bond contiennent des parametres (membres de classe) inhérents au squelette de la

molécule : comme par exemple charge atomique, nombre d'électrons, pour l'atome
la classe Bond possède uen référence sur les deux atomes qui contiennent la liaison et un type de laiison "int" : 1

2 ou 3 suivant si c'est une liaison triple ou double.
Ces deux classes ne sont pas "interne" à la molécule pour plus de lisibilité, donc elles contiennent une référence

à la molécule qui les incluent : je ne sais pas si cela est efficace, j'aurai peut etre dû mettre ces classes à

l'intérieur de la lcase molécule.


mais les classes Atom et Bond ont actuellement aussi des paramètres inhérents à la théorie de huckel : double hX

pour l'atome et double hxy pour la liaison (bond) . quand on modifie le type d'atome (Carbone, Azote, etc....

propriété inhérente au squelette) le paramètre hx est modifié sur l'atome, mais cela va aussi modifier le

paramètre Hxy dans toutes les liaisons de la molécule qui possèdent l'atome. pour cela qd on fait un "set" sur

l'atome, l'objet appelle ensuite une fonction "handle...." dans la molécule qui va faire les modifs sur les

liaisons. Apres chaque modif apportée sur la molécule ou une liaison ou un atome l'objet molécule envoie des

évenements aux vues par des listeners que j'ai créé (classe MoleculeEvent, interface MoleculeListener) .
Bref voilà ma question .

comment puis-je séparer ce qui est inhérent au squelete et et ce qui est inhérent à huckel ???

En effet j'aimerai bien que mon suqelette de base soit réutilisable pour des logiciels qui n'ont rien à voir avec

huckel.

j'avias pensé au départ faire une classe Skeleton qui contient des listes d'AtomSekel et de BondSekel ayant

simplement eux meme des propriété inhétentes aux squelette, et dérivée AtomSkel et BondSkel en AtomHuckel et

BondHuckel., puis dérivée Skeleton et MoleculeHuckel.
Cela n'est pas possible parce que par dérivation les arraylist de MoleculeHuckel n'auront pas AtomSkel et des

BondSkel mais simlplement des AtomHuckel et des BondHuckel.

Comment faire ? j'ai 'impression que je dois tout mettre dans la même classe et qu'il est impossible de dériver un

conteneur d'objet contenant un contenu lui-même dérivé

En vous remerciant par avance

Cordialement
  • # Interface

    Posté par  . Évalué à 3.

    Je n'ai pas tout compris à ton pb car je ne connais pas le domaine mais mais si j'ai bien compris tu souhaites composer 2 comportements dans une seul classe d'implémentation et séparer leur contrats. Les interfaces (interface en java) et la délégation peuvent répondre à ton pb

    Par exemple, tu peux créer un interface AtomHuckelInt qui déclare toutes les opérations liée aux spécificités Huckel des atomes (setHx, ....). Tu crées une classe d'implémentation AtomHuckelImpl qui implémente cette interface.

    Tes classe de base (Atom, ..)ne déclarent et n'implémentent que les méthodes de bases.
    Tu crées une classe AtomHuckel qui hérite de Atom et qui implemente l'interface AtomHuckelInt.
    A l'intérieur, tu encapsules une référence à la classe AtomHuckelImpl (composition=> attribut privé par exemple private AtomHuckelImpl ah) dans l'implémentation des méthodes de l'interface tu délegues le comportement à ta réference privée par simple appel de méthode ( ah.setHx() )

    Voici 2 liens qui explique le fonctionnement

    http://www.artima.com/designtechniques/compoinh.html

    En espérant ne pas avoir tapé à coté du sujet.
    • [^] # Re: Interface

      Posté par  . Évalué à 3.

      Juste une petite précision:


      Comment faire ? j'ai 'impression que je dois tout mettre dans la même classe et qu'il est impossible de dériver un conteneur d'objet contenant un contenu lui-même dérivé


      Pardonnes moi si je t'enonce des concepts que tu maîtrises déjà, je n'ai peut-être pas bien compris ta problématique?
      .
      En POO si tu déclares une méthode dans une classe qui attend des objets d'une certaine classe et leur applique un traitement. Le code de cette méthode pourra parfaitement fonctionner si les objets référencés sont en fait des instances d'une classe dérivée de celle déclarée. Dans le traitement de la méthode, ils seront considérés comme des objets de la classe mère attendue et les méthodes correspondantes seront invoquées. En java, si ces méthodes ont été redéfinies dans les sous classe c'est l'implémentation de la sous classe qui sera appelée. On parle alors de polymorphisme.
      http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented(...)

      Dans ton cas donc si AtomHuckel est dérivé de AtomSkel et que tu traites un ArrayList de AtomSkel dans ta classe Molecule. Le code fonctionnera à l'identique si l'ArrayList contient en fait des références à des AtomHuckel.

      Autre chose, je ta'ai donnné unline qui explique l'intêret de la composition.
      Voici un article qui traite plus précisément de la délégation
      http://en.wikipedia.org/wiki/Delegation_%28programming%29
      • [^] # Re: Interface

        Posté par  . Évalué à 1.

        Voici un exemple concret de mon problème . c'est analogue à mon probleme car je dois gérer des copies de molécules de huckel.
        en fait ds l'exemple ci dessous

        A = Atom de base
        AA : atom huckel
        contA : squelette de la molécule . j'ai besoin d'un constucteur par copie

        dans mon main quand je fais une iteration sur la copie du conteneur ca plante sur le cast , forcément, pcq je caste en AA et que mon constructeur par copie ne copie que des objets de classe A foaut -il donc que je fasse un nouveau conteneur contAA ? et que donc pour gérer des objets AA je ne me serve plus du tout de contA ?

        public class A {
        public int a;
        public A(int a) {
        this.a = a;
        }
        public A(A other) {
        this.a = other.a;
        }
        }

        public class AA extends A {
        public int aa;
        public AA (int a, int aa) {
        super (a);
        this.aa = aa;
        }
        public AA (AA other) {
        super (other);
        this.aa = other.aa;
        }
        }


        import java.util.ArrayList;
        import java.util.Iterator;

        public class ContA {
        public ArrayList contA;
        public ContA() {
        contA = new ArrayList ();
        }

        public ContA(ContA other) {
        contA = new ArrayList ();
        Iterator it = other.contA.iterator();
        A a;
        while (it.hasNext()) {
        a = (A) it.next();
        this.contA.add(new A (a));
        }
        }
        }



        import java.util.Iterator;

        public class Main {

        /**
        * @param args
        */
        public static void main(String[] args) {
        ContA myContA = new ContA();
        AA a1 = new AA(11, 20);
        AA a2 = new AA(12, 25);
        myContA.contA.add(a1);
        myContA.contA.add(a2);
        Iterator it = myContA.contA.iterator();
        AA a;
        while (it.hasNext()) {
        a = (AA) it.next();
        System.out.println(a.a + " " + a.aa);
        }
        ContA copyContA = new ContA(myContA);

        it = copyContA.contA.iterator();
        while (it.hasNext()) {
        a = (AA) it.next();
        System.out.println(a.a + " " + a.aa);
        }
        }

        }
        • [^] # Re: Interface

          Posté par  . Évalué à 2.

          Ok je comprend mieux ton problème.

          La solution est peut être de recourir aux types paramétrés (genérics pour java, templates pour C++,...)
          public class ContA {
          ....
          http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf

          Par contre tu ne pourras pas mélanger des objets de type différents
          dans un même conteneur. Dans ton exemple ca n'est pas le cas doncca devrait marcher.
          Ca nécessite aussi au minimum un JDK 1.5
          • [^] # Re: Interface

            Posté par  . Évalué à 2.

            Désolé pour être plus précis

            public class ContA {
            public ArrayList contA;
            ....
            }

            ....


            public class Main {

            /**
            * @param args
            */
            public static void main(String[] args) {
            ContA myContA = new ContA();
            AA a1 = new AA(11, 20);
            AA a2 = new AA(12, 25);
            myContA.contA.add(a1);
            myContA.contA.add(a2);
            Iterator it = myContA.contA.iterator();
            AA a;
            while (it.hasNext()) {
            a = (AA) it.next();
            System.out.println(a.a + " " + a.aa);
            }
            ContA copyContA = new ContA(myContA);

            it = copyContA.contA.iterator();
            while (it.hasNext()) {
            a = (AA) it.next();
            System.out.println(a.a + " " + a.aa);
            }
            }

            L'idée est là mais ya sûrement des erreurs de syntaxe

            Tiens nous au courant de tes aventures
            • [^] # Re: Interface

              Posté par  . Évalué à 2.

              Arghh les chevrons passent pas

              je la refais
              public class ContA<E> {
              public ArrayList<E> contA;
              ....
              }

              ....


              public class Main {

              /**
              * @param args
              */
              public static void main(String[] args) {
              ContA<AA> myContA = new ContA<AA>();
              AA a1 = new AA(11, 20);
              AA a2 = new AA(12, 25);
              myContA.contA.add(a1);
              myContA.contA.add(a2);
              Iterator it = myContA.contA.iterator();
              AA a;
              while (it.hasNext()) {
              a = (AA) it.next();
              System.out.println(a.a + " " + a.aa);
              }
              ContA<AA> copyContA = new ContA<AA>(myContA);

              it = copyContA.contA.iterator();
              while (it.hasNext()) {
              a = it.next();
              System.out.println(a.a + " " + a.aa);
              }
              }

              Sinon en passant ce n'est en général pas une bonne idée de déclarer les attributs d'une classe public. Ca casse l'encapsulation et si tu décides de changer l'implémentation de ta classe (remplacer des ArrayList par atre chose par exemple) tu seras obligé de modifier tout ton code dans toutes les methodes appelantes.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.