TP7q3

Programmation Avancée

Modérateur : Douin

Joris_Oziol
Messages : 52
Inscription : 15 oct. 2016 13:59

TP7q3

Message par Joris_Oziol » 16 déc. 2016 12:43

Petit problème voir gros ...
je prends toutes les methodes locales dans un premier temps (getDeclaredMethod)
Puis je récupère toutes les methodes locales et heritées dans deuxième temps (getMethod)
Puis je mets dans une map mes methodes si elles sont public ou protégées
Par contre je rencontre le problème suivant, c'est de savoir comment faire une pseudo soustraction pour enlevé les methodes locales de celles qui sont héritées
Les tests fonctionnent pour java.lang.Object mais par pour java.util.AbstractCollection

Si une âme charitable a une idée pour m'aiguiller dans mon code ...

Merci d'avance

Code : Tout sélectionner

package question3;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.Iterator;
import java.lang.reflect.Modifier;

public class Introspection{
    public static Set<Method> getHeritees(String nomDeLaClasse) throws ClassNotFoundException{
        Set<Method> allMethods = new HashSet<Method>();

        Class cl = Class.forName(nomDeLaClasse);

        //Method[] methodesSuperClasse = cl.getMethods();

        Map<Method, Integer> map =  new HashMap<Method,Integer>();

        for(Method m : cl.getMethods()){
            int compteur = 0;
            Class superClass = cl.getSuperclass();
            Class[] interfaces =cl.getInterfaces();
            while(superClass!=null){
                try{
                    superClass.getDeclaredMethod(m.getName(), m.getParameterTypes());
                    compteur++;
                }catch(NoSuchMethodException e){

                }
                superClass = superClass.getSuperclass();
            }
            for(int i=0; i < interfaces.length;i++){
                try{
                    interfaces[i].getMethod(m.getName(), m.getParameterTypes());
                    compteur++;
                }catch(NoSuchMethodException e){

                }
            }

            int mod = m.getModifiers();
            if(mod!=0){
                if(Modifier.isPublic(mod)|| Modifier.isProtected(mod)){
                    map.put(m,compteur);
                }
            }

        }

        Iterator it = map.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry kv = (Map.Entry)it.next();
            Method currentMethod = (Method)kv.getKey();
            Integer superClasses = (Integer)kv.getValue();
            if(superClasses == 1){

                allMethods.add(currentMethod);

            }
            it.remove();
        }

        return allMethods;

    }

    public static void main(String[] args) throws ClassNotFoundException{
        for(Method m : Introspection.getHeritees("java.util.AbstractCollection")){
            System.out.println(m);
        }
    }

}

Joris_Oziol
Messages : 52
Inscription : 15 oct. 2016 13:59

Re: TP7q3

Message par Joris_Oziol » 16 déc. 2016 12:44

De plus comment "voir" le fait que ce soit redéfini localement ...

ibcht
Messages : 1
Inscription : 04 déc. 2016 20:01

Re: TP7q3

Message par ibcht » 17 déc. 2016 2:19

Bonjour,

Pour la soustraction, il faudrait tester l'égalité des paramètres, du type de retour (à la covariance près ?) ainsi que du nom des méthodes, puis en cas d'égalité, faire un remove() de la méthode héritée dans ton Set.

Par contre, quelque chose me chiffonne : d'après la capture d'écran fourni dans l'énoncé, il faudrait aussi retourner les méthodes protégées. Seulement, getMethod() ne retourne que les méthodes héritées qui sont publiques !

La solution serait-elle d'introspecter chacune des classes parentes pour en récupérer les méthodes publiques ET protégées?

Irénée

tasic
Messages : 28
Inscription : 09 oct. 2016 14:13

Re: TP7q3

Message par tasic » 17 déc. 2016 17:56

Tu peux utiliser getDeclaredMethods (qui te liste tout)
et virer les private et public abstract ça marche bien aussi

Joris_Oziol
Messages : 52
Inscription : 15 oct. 2016 13:59

Re: TP7q3

Message par Joris_Oziol » 17 déc. 2016 19:14

"
Dernière édition par Joris_Oziol le 17 déc. 2016 22:15, édité 1 fois.

Joris_Oziol
Messages : 52
Inscription : 15 oct. 2016 13:59

Re: TP7q3

Message par Joris_Oziol » 17 déc. 2016 22:12

Après une nième tentatives j'ai :

Code : Tout sélectionner

public class Introspection{
    public static Set<Method> getHeritees(String nomDeLaClasse) throws ClassNotFoundException{
        Set<Method> allMethods = new HashSet<Method>();

        Class<?> cl = Class.forName(nomDeLaClasse);

        Map<Method, List<Class<?>>> map = new HashMap<Method,List<Class<?>>>();

        Class<?> classe = cl.getSuperclass();    
        while(classe != null){    
            classe = cl.getSuperclass();
            for(Method m : classe.getDeclaredMethods()){
                
               try{
                    classe.getDeclaredMethod(m.getName(), m.getParameterTypes());
                    List<Class<?>> liste = map.get(m);
                    if( liste==null) {
                        liste = new ArrayList<Class<?>>();
                    }
                    liste.add(classe);
                    int mod = m.getModifiers();
                    if(mod!=0){
                        if(Modifier.isPublic(mod)|| Modifier.isProtected(mod)){
                            //System.out.println(" méthode : " + m);
                            map.put(m,liste);
                        }
                    }
                    
                }catch(NoSuchMethodException e){
                }
                   
            }
             classe = classe.getSuperclass();
        }
        
        Iterator it = map.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry kv = (Map.Entry)it.next();
            Method currentMethod = (Method)kv.getKey();
            List superClasses = (List)kv.getValue();
            for(int j = 0; j < superClasses.size(); j++){
                allMethods.add(currentMethod);
            }
            it.remove();
        }

        return allMethods;
    }

    public static void main(String[] args) throws ClassNotFoundException{
        for(Method m : Introspection.getHeritees("java.util.AbstractCollection")){
            System.out.println(m);
        }
    }

}

Par contre Jnews ne veut plus me tester "Une erreur est survenue pendant la phase des tests "...

Voici le résultat du main :
protected void java.lang.Object.finalize() throws java.lang.Throwable
public java.lang.String java.lang.Object.toString()
protected native java.lang.Object java.lang.Object.clone() throws java.lang.CloneNotSupportedException
public final native void java.lang.Object.notify()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final native java.lang.Class java.lang.Object.getClass()
public native int java.lang.Object.hashCode()
public boolean java.lang.Object.equals(java.lang.Object)
public final native void java.lang.Object.notifyAll()
J'ai
public java.lang.String java.lang.Object.toString()
qui ne devrait pas être là ... et je ne sais pas pourquoi il est là ...

Une idée ?

Joris_Oziol
Messages : 52
Inscription : 15 oct. 2016 13:59

Re: TP7q3

Message par Joris_Oziol » 17 déc. 2016 23:19

Plus que 11 erreurs ...

Code : Tout sélectionner

public class Introspection{
    public static Set<Method> getHeritees(String nomDeLaClasse) throws ClassNotFoundException{
        Set<Method> allMethods = new HashSet<Method>();

        Class<?> cl = Class.forName(nomDeLaClasse);
        List<Class<?>> liste1 = null  ;
        List<Class<?>> liste2 = null  ;
        Map<Method, List<Class<?>>> map = new HashMap<Method,List<Class<?>>>();

        Class<?> classe = cl.getSuperclass();    
        while(classe != null){    
            //classe = cl.getSuperclass();
            for(Method m : classe.getDeclaredMethods()){

                try{
                    classe.getDeclaredMethod(m.getName(), m.getParameterTypes());
                    liste1 = map.get(m);
                    if( liste1==null) {
                        liste1 = new ArrayList<Class<?>>();
                    }
                    liste1.add(classe);
                    int mod = m.getModifiers();
                    //Class<?> test = Class.forName("java.lang.String");
                    if(mod!=0){
                        //if(m.getReturnType()!= test){
                        if(Modifier.isPublic(mod) || Modifier.isProtected(mod)|| Modifier.isStrict(mod) ){

                            System.out.println(" méthode : " + m.getReturnType());
                            map.put(m,liste1);
                        }//}
                    }

                }catch(Exception e){
                }

            }
            classe = classe.getSuperclass();
        }
       
            
            
        

        Iterator it = map.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry kv = (Map.Entry)it.next();
            Method currentMethod = (Method)kv.getKey();
            List superClasses = (List)kv.getValue();
            for(int j = 0; j < superClasses.size(); j++){
                allMethods.add(currentMethod);
            }
            it.remove();
        }

        return allMethods;
    }

    public static void main(String[] args) throws ClassNotFoundException{
        for(Method m : Introspection.getHeritees("java.util.AbstractCollection")){
            System.out.println(m);
        }
    }

}
Si jamais je décommente j'ai le bon résultat mais c'est pas ce que l'on recherche ...

gautierd
Messages : 49
Inscription : 12 oct. 2016 14:55

Re: TP7q3

Message par gautierd » 18 déc. 2016 17:10

Bonjour à tous,
J'apporte moi aussi mes questions.

J'ai une stratégie différente,
1) Je récupère toutes les méthode de la classe à tester
2) Pour toutes les classes parents
Je récupère toutes les méthodes de la classe mère en cours
Pour toutes les méthodes récupérées, je regarde s'il y en a une contenue dans les méthodes à tester
Si oui, c'est qu'elle a été redéfinie. Si non, je l'ajoute dans le set.

Avec le code suivant :

Code : Tout sélectionner

public class Introspection{

    public static Set<Method> getHeritees(String nomDeLaClasse) throws ClassNotFoundException {
        Set<Method> resultat = new HashSet<Method>();
        Class<?> classDescriptor = Class.forName(nomDeLaClasse);
        List<Method> declaredMThis = new ArrayList<Method>(Arrays.asList(classDescriptor.getDeclaredMethods())); 
        List<Method> methodesSuperClass = null;
        boolean found = false;
        while (classDescriptor != null)
        {
            methodesSuperClass = new ArrayList<Method>(Arrays.asList(classDescriptor.getDeclaredMethods()));
            for (Method m : methodesSuperClass) 
            {
                found = false;
                for (Method eachMethod : declaredMThis)
                {
                    if ( (eachMethod.getName()==m.getName()) && (eachMethod.getParameterCount()==m.getParameterCount()) && (eachMethod.getReturnType().getClass() == m.getReturnType().getClass() ))
                    {
                        found = true;
                        if (eachMethod.getParameterCount()>0)
                        {
                            Parameter[] pEachMethod = eachMethod.getParameters();
                            Parameter[] pM = m.getParameters();
                            for (int index = 0; index < eachMethod.getParameterCount() ; index++)
                            {
                                if (pEachMethod[index].getClass() != pM[index].getClass())
                                {
                                    found = false;
                                }
                            }
                        }
                    }
                }
                if (found == false)
                {
                        resultat.add(m);
                }
            }
            System.out.println("*******************");
            classDescriptor = classDescriptor.getSuperclass();
        }

        System.out.println("Resultat\n------------------");
        System.out.println(declaredMThis);
        System.out.println(resultat.size());
        
        for (Method m : resultat)
        {
            System.out.println(m.getName());
        }

        return resultat;
    }
J'obtiens bien la sortie indiquée sur l'énoncé pour la classe donnée en exemple.
Si je teste avec une autre classe, çà ne marche pas.
Exemple, dans le cas Vector, j'obtiens
finalize
registerNatives
outOfBoundsMsg
notify
finishToArray
wait
wait
wait
getClass
rangeCheckForAdd
notifyAll
C'est presque bon sauf que je ne devrais pas avoir outOfBoundsMsg finishToArray rangeCheckForAdd registerNatives

Que sont ces méthodes alors qu'elles ne sont pas sensées y être.

Merci d'avance pour vos idées.

TSwank
Messages : 15
Inscription : 05 juin 2014 11:03

Re: TP7q3

Message par TSwank » 18 déc. 2016 19:06

Bonjour,

Pour enlever certains "parasites", il faut vérifier aussi que la méthode n'est pas abstraite et bien en accès public ou protected.

Cordialement,
Thomas

gautierd
Messages : 49
Inscription : 12 oct. 2016 14:55

Re: TP7q3

Message par gautierd » 18 déc. 2016 20:22

Ah han ...
Bon, ben je vais essayer.
Si j'y arrive tant mieux et sinon tant pis. J'espère qu'il y a pas plus d'astuces parce que sinon ce sera pas évident. gautier

gautierd
Messages : 49
Inscription : 12 oct. 2016 14:55

Re: TP7q3

Message par gautierd » 18 déc. 2016 21:36

Je te remercie pour ton aide.
Cela m'affectivement corrigé cette erreur.

J'ai donc le code suivant où je vérifie que les méthodes des classes mères sont public ou protected et non abtract.

Code : Tout sélectionner

public class Introspection{

    public static Set<Method> getHeritees(String nomDeLaClasse) throws ClassNotFoundException {
        Set<Method> resultat = new HashSet<Method>();
        Class<?> classDescriptor = Class.forName(nomDeLaClasse);
        List<Method> declaredMThis = new ArrayList<Method>(Arrays.asList(classDescriptor.getDeclaredMethods())); 
        List<Method> methodesSuperClass = null;
        boolean found = false;
        while (classDescriptor != null)
        {
            methodesSuperClass = new ArrayList<Method>(Arrays.asList(classDescriptor.getDeclaredMethods()));
            for (Method m : methodesSuperClass) 
            {
                found = false;
    [color=#FF0000]            if (   ( (Modifier.isProtected(m.getModifiers())) || (Modifier.isPublic(m.getModifiers())) )  && (!Modifier.isAbstract(m.getModifiers())))    [/color]
                {
                    for (Method eachMethod : declaredMThis)
                    {
                        if ( (eachMethod.getName()==m.getName()) && (eachMethod.getParameterCount()==m.getParameterCount()) && (eachMethod.getReturnType().getClass() == m.getReturnType().getClass() ))
                        {
                            found = true;
                            if (eachMethod.getParameterCount()>0)
                            {
                                Parameter[] pEachMethod = eachMethod.getParameters();
                                Parameter[] pM = m.getParameters();
                                for (int index = 0; index < eachMethod.getParameterCount() ; index++)
                                {
                                    if (pEachMethod[index].getClass() != pM[index].getClass())
                                    {
                                        found = false;
                                    }
                                }
                            }
                        }
                    }
                    if (found == false)
                    {
                        resultat.add(m);
                    }
                }
            }
            System.out.println("*******************");
            classDescriptor = classDescriptor.getSuperclass();
        }

        System.out.println("Resultat\n------------------");
        System.out.println(resultat.size());

        for (Method m : resultat)
        {
            System.out.println(m.getName());
        }

        return resultat;
    }
Néanmoins, après test JEWS j'ai
1) test_javax_swing_JApplet(question3): nombre de methodes heritees errone ??? expected:<283> but was:<318> 2) test_java_util_une_classe_au_hasard(question3): en 1.8.0_91, nombre de methodes heritees errone ??? expected:<38> but was:<42> 3) test_java_util_WeakHashMap(question3): nombre de methodes heritees errone ??? expected:<11> but was:<15> 4) test_java_util_AbstractSet(question3): nombre de methodes heritees errone ??? expected:<19> but was:<20> 5) test_javax_swing_JButton(question3): nombre de methodes heritees errone ??? expected:<429> but was:<518> 6) test_classe_au_clone_public(question3): clone devient public dans la sous-classe ??? expected:<11> but was:<10> 7) test_java_util_Stack(question3): nombre de methodes heritees errone ??? expected:<57> but was:<88> 8) test_java_util_HashSet(question3): nombre de methodes heritees errone ??? expected:<16> but was:<20>
Je pense pas être loin mais bon là je sais pas.

TSwank
Messages : 15
Inscription : 05 juin 2014 11:03

Re: TP7q3

Message par TSwank » 19 déc. 2016 11:47

Bonjour,

Je pense que tu dois ajouter deux choses:
- la covalence pour la vérification de la valeur de retour
- il ne faut pas prendre en compte les méthodes des sous classes qui sont elles-mêmes redéfinies par une sous-classe supérieur

Bon courage

Joris_Oziol
Messages : 52
Inscription : 15 oct. 2016 13:59

Re: TP7q3

Message par Joris_Oziol » 19 déc. 2016 12:09

En m'aidant de la réponse de gautierd

Code : Tout sélectionner

package question3;

import java.lang.reflect.*;
import java.util.*;

public class Introspection{
    public static Set<Method> getHeritees(String nomDeLaClasse) throws ClassNotFoundException{
        Set<Method> allMethods = new HashSet<Method>();

        Class<?> cl = Class.forName(nomDeLaClasse);
        Class<?> classe = cl.getSuperclass(); 
        List<Class<?>> liste1 = null  ;
        List<Method> liste2 = new ArrayList<Method>(Arrays.asList(cl.getDeclaredMethods()));
        
        boolean found = false;
        Map<Method, List<Class<?>>> map = new HashMap<Method,List<Class<?>>>();
 
        while(classe != null){    
            
            for(Method m : classe.getDeclaredMethods()){
                found = false;
                try
                {
                    classe.getDeclaredMethod(m.getName(), m.getParameterTypes());
                    liste1 = map.get(m);
                    if( liste1==null) {
                        liste1 = new ArrayList<Class<?>>();
                    }
                    liste1.add(classe);
                    int mod = m.getModifiers();
                   
                    if(mod!=0)
                    {
                        
                        if(Modifier.isPublic(mod) || Modifier.isProtected(mod)&& (!Modifier.isAbstract(mod)) )
                        {
                            for (Method m1 : liste2)
                            {
                                if ( (m1.getName()==m.getName()) && (m1.getParameterCount()==m.getParameterCount()) && (m1.getReturnType().getClass() == m.getReturnType().getClass() ))
                                {
                                    found = true;
                                    if (m1.getParameterCount()>0)
                                    {
                                        Parameter[] pM1 = m1.getParameters();
                                        Parameter[] pM = m.getParameters();
                                        for (int i = 0; i < m1.getParameterCount() ; i++)
                                        {
                                            if (pM1[i].getClass() != pM[i].getClass())
                                            {
                                                found = false;
                                            }
                                        }
                                    }
                                }
                            }
                             if (found == false)
                            {
                                map.put(m,liste1);
                            }      
                            
                        }
                    }
                    
                }catch(Exception e){
                }

            }
            classe = classe.getSuperclass();
        }

        Iterator it = map.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry kv = (Map.Entry)it.next();
            Method currentMethod = (Method)kv.getKey();
            List superClasses = (List)kv.getValue();
            for(int j = 0; j < superClasses.size(); j++){
                allMethods.add(currentMethod);
            }
            it.remove();
        }

        return allMethods;

    }

    public static void main(String[] args) throws ClassNotFoundException{
        for(Method m : Introspection.getHeritees("java.util.AbstractCollection")){
            System.out.println(m);
        }
    }

}
j'ai le bon résultat mais jnews n'ai pas content ... je compte trop de méthodes héritées ...

pellier
Messages : 37
Inscription : 30 oct. 2016 21:13

Re: TP7q3

Message par pellier » 19 déc. 2016 15:12

Bonjour

@TSwank :
il faut vérifier aussi que la méthode n'est pas abstraite et bien en accès public ou protected.
Pourquoi supprimer les méthodes abstraites ?

gautierd
Messages : 49
Inscription : 12 oct. 2016 14:55

Re: TP7q3

Message par gautierd » 19 déc. 2016 20:06

Merci TSwank, que faut-il vérifier pour la covalence ? Que le type de retour de la classe fille est un sous type du retour des méthodes dans les classes supérieures ?

Répondre

Qui est en ligne ?

Utilisateurs parcourant ce forum : Aucun utilisateur inscrit et 1 invité