Choisir quelle classe peut en instancier une autre

Résolu
Whismeril
Messages postés
17478
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
2 juillet 2022
- 12 nov. 2015 à 19:30
Whismeril
Messages postés
17478
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
2 juillet 2022
- 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
17478
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
2 juillet 2022
600
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
17478
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
2 juillet 2022
600
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
16564
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
2 juillet 2022
124
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
17478
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
2 juillet 2022
600
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
14941
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
20 juin 2022
161
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
16564
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
2 juillet 2022
124
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
17478
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
2 juillet 2022
600
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