Choisir quelle classe peut en instancier une autre

Résolu
Whismeril Messages postés 19027 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 24 avril 2024 - 12 nov. 2015 à 19:30
Whismeril Messages postés 19027 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 24 avril 2024 - 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.

4 réponses

Whismeril Messages postés 19027 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 24 avril 2024 656
13 nov. 2015 à 10:31
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.
1
Whismeril Messages postés 19027 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 24 avril 2024 656
13 nov. 2015 à 20:24
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
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 127
13 nov. 2015 à 21:00
"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);
0
Whismeril Messages postés 19027 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 24 avril 2024 656
13 nov. 2015 à 21:10
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.
0
NHenry Messages postés 15113 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 22 avril 2024 159
Modifié par NHenry le 12/11/2015 à 19:38
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"
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 127
12 nov. 2015 à 20:05
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());
             // ...
         }
    }
}
0
Whismeril Messages postés 19027 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 24 avril 2024 656
12 nov. 2015 à 23:19
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.
0
Rejoignez-nous