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

Signaler
Messages postés
14843
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
23 mai 2020
-
Messages postés
14843
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
23 mai 2020
-
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.

4 réponses

Messages postés
14843
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
23 mai 2020
405
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.
Messages postés
14843
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
23 mai 2020
405
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
Messages postés
16220
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
20 mai 2020
92
"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);
Messages postés
14843
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
23 mai 2020
405
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.
Messages postés
14665
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
15 mai 2020
143
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"
Messages postés
16220
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
20 mai 2020
92
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());
             // ...
         }
    }
}
Messages postés
14843
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
23 mai 2020
405
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.