Choisir quelle classe peut en instancier une autre [Résolu]

Messages postés
13650
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
25 août 2019
- - Dernière réponse : Whismeril
Messages postés
13650
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
25 août 2019
- 13 nov. 2015 à 21:10
Bonsoir,

je me casse les dents sur ce problème depuis quelques jours.

J'ai besoin d'une classe static, qui initialise une liste d'une autre classe (Test).
Le reste du programme n'a accès qu'à une instance de cette liste via à accesseur.
Pour le reste du programme
  • les propriétés de Test doivent être en lecture seule.
  • il ne doit pas être possible d'instancier Test



Un exemple:
    public static class SeuleClasseOuOnPeutInitialiserTest
    {
        private static List<Test> tests;

        static SeuleClasseOuOnPeutInitialiserTest()
        {
            tests = new List<Test>();

            //Ici j'ai besoin de pouvoir ajouter des instances de Test dans la liste, avec des valeurs, mais que cela ne soit pas possible ailleurs.
        }

        public static Test MonTest(int index)
        {
            return tests[index];
        }

    }

    public class Test
    {
        public int Entier { get; private set; }

        public double Decimal { get; private set; }
    }


J'ai essayer de dériver SeuleClasseOuOnPeutInitialiserTest de Test, ça marche si SeuleClasseOuOnPeutInitialiserTest n'est pas static, mais je n'ai pas trouvé comment faire dans mon cas.

Existe t il un moyen pour qu'un constructeur ne soit visible que de SeuleClasseOuOnPeutInitialiserTest?

Ou une autre idée?

Merci d'avance.
Afficher la suite 

4 réponses

Meilleure réponse
Messages postés
13650
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
25 août 2019
298
1
Merci
Merci à tous les deux,

La classe incorporée dans l'autre sens, le constructeur privé et le modificateur sealed (pour que personne ne puisse dériver la classe) et ça marche comme on me le demande.

Je poste le code d'exemple ce soir, c'est un peu casse c.... avec la tablette.

Dire « Merci » 1

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 111 internautes nous ont dit merci ce mois-ci

Whismeril
Messages postés
13650
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
25 août 2019
298 -
Voila le code
    public sealed class Test
    {
        private Test(){}

        private Test(int entier, double decimale)
        {
            Entier = entier;
            Decimal = decimale;
        }

        public int Entier { get; protected set; }

        public double Decimal { get; protected set; }


        public static class SeuleClasseOuOnPeutInitialiserTest
        {
            private static List<Test> tests;

            static SeuleClasseOuOnPeutInitialiserTest()
            {
                tests = new List<Test>();
                tests.Add(new Test(1, 2.1));
                tests.Add(new Test {Entier = 2, Decimal= 2.3});
            }

            public static Test MonTest(int index)
            {
                return tests[index];
            }

        }


    }


Le seul petit inconvénient est que pour utiliser SeuleClasseOuOnPeutInitialiserTest il faut appeler Test. SeuleClasseOuOnPeutInitialiserTest
KX
Messages postés
16010
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
24 août 2019
86 -
"Le seul petit inconvénient est que pour utiliser SeuleClasseOuOnPeutInitialiserTest il faut appeler Test. SeuleClasseOuOnPeutInitialiserTest"

En gros ça va te donner quoi ?

SeuleClasseOuOnPeutInitialiserTest initializer = new SeuleClasseOuOnPeutInitialiserTest();
Test test = initializer.MonTest(2);

Perso, ça ne me choque pas vraiment...
Après ça dépend ce que tu veux faire exactement, mais moi j'irais probablement encore plus loin en attribuant à Test une méthode static qui retourne une instance de SeuleClasseOuOnPeutInitialiserTest :

public static SeuleClasseOuOnPeutInitialiserTest BuildInitializer() {
    return new SeuleClasseOuOnPeutInitialiserTest();
}

Ce qui donnerait par exemple :

Test test = Test.BuildInitializer().MonTest(2);
Whismeril
Messages postés
13650
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
25 août 2019
298 -
J'ai bien dit que cet inconvénient est petit. ;-)!

En fait le vrai code contient, plusieurs méthodes static qui d'une façon ou d'une autre retourne un ou plusieurs éléments de la liste.

Pour l'extérieur, le comportement interne doit rester opaque, les champs en lecture seule et les classes non instanciables.

Les algos de cette dll sont du ressort du secret industriel.
On fait une sorte de prototype du programme dans son ensemble (ohm minimaliste, fonctionnalités minimales), mais une version "améliorée" sera peut être sous traitée ultérieurement.
On décrira juste au titulaire les entrées et sorties de la dll.
Commenter la réponse de Whismeril
Messages postés
14525
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
25 août 2019
133
0
Merci
Tu peux normalement jouer sur la visibilité du constructeur d'instance (usuellement Public, Private, Internal, Protected)
Dans ton cas, un Protected serait peut être utilisable.

Après, les membres statiques ne peuvent être affectés par l'héritage (éventuellement masqué, mais uniquement si l'appel est fait par une classe enfant)

J'interviens principalement en VB6 et VB.NET, avec un peu de C#, mais la modération m'amène souvent sur d'autre langages.
En VB.NET pensez à activer "Option Explicit" et "Option Strict"
Commenter la réponse de NHenry
Messages postés
16010
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
24 août 2019
86
0
Merci
Bonsoir,

En Java on peut déclarer une classe dans une autre auquel cas elle possède tous son contenu, même privé, je ne sais pas si l'équivalent existe en C#

public final class Test {

    private Test() {
    }

    public static class SeuleClasseOuOnPeutInitialiserTest {

         private static final List<Test> tests = new List<Test>();

         static {
             tests.add(new Test());
             // ...
         }
    }
}
Commenter la réponse de KX
Messages postés
13650
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
25 août 2019
298
0
Merci
Bonsoir à tous les deux,

concernant le constructeur masqué, j'ai essayé, mais comme la classe statique ne peut pas dériver d'une classe instanciable ça ne convient pas à mon besoin.

pour la classe incorporée, ça existe (bien que le mot clé static n'ait pas le même sens dans les 2 langages), et j'ai essayé dans l'autre sens (Test dans SeuleClasseOuOnPeutInitialiserTest), je n'ai pas penser à inverser pour voir ce que cela donne.

Je tente ça demain.
Commenter la réponse de Whismeril