0
votes

Puis-je empêcher une variable privée d'être modifiée par d'autres objets de la même classe?

Je suis en train de lire un jeu en temps réel et j'aimerais empêcher que les variables d'état des objets sur un thread soient définies à partir d'un autre thread. Cela rendra la prévention des conditions de concurrence beaucoup plus facile.

Je voudrais cependant pouvoir lire l'état des autres objets. J'ai l'intention d'utiliser un système à double tampon, dans lequel un objet d'état est utilisé comme tampon d'arrêt et effectue des changements d'état tandis que l'autre est utilisé comme tampon arrière et fournit l'état (de l'image précédente) à d'autres objets. J'ai besoin de pouvoir lire les informations d'état du backbuffer pour apporter des modifications dans le buffer.

Le problème est que même si le setter de variables est privé, il est possible de le changer à partir d'un autre objet de la même classe .

    public class State
    {
        //Some example state information
        public string StateVar1 { get; private set; }

        //This method will be farmed out to multiple other threads
        public void Update(State aDifferentStateObject)
        {
            StateVar1 = "I want to be able to do this";
            string infoFromAnotherObject = aDifferentStateObject.StateVar1; //I also want to be able to do this
            aDifferentStateObject.StateVar1 = "I don't want to be able to do this, but I can";
        }
    }


2 commentaires

Ce que vous essayez de faire n'a aucun sens. En tant qu'auteur du cours, vous avez un contrôle total sur ce qu'il fait. Si vous ne voulez pas que l'instance de votre classe modifie les propriétés d'autres instances, ne le faites pas.


Vous avez raison, j'ai le contrôle sur ce que j'écris dans ce cours. Cependant, je ne suis pas infaillible, je ne peux pas être sûr à 100% que personne d'autre ne modifiera jamais cette classe, et les conditions de course sont notoirement difficiles à déboguer. Il s'agit d'un mécanisme de défense contre les erreurs futures.


4 Réponses :


0
votes

il est possible de le changer à partir d'un autre objet de la même classe.

Vous ne pouvez pas empêcher votre propre classe de définir des setters privés.

Je veux dire après tout, vous êtes l'auteur de ce cours, ce sont seulement vos doigts dont vous devez vous soucier.

private string backingField;

public string StateVar1
{
    get => backingField;
}

Si vous souhaitez empêchez-vous de changer votre propre membre, puis utilisez une méthode d'extension

public string StateVar1 { get; }

ou rendez-le vraiment en lecture seule (bien que ce ne soit probablement pas utile)

public class Extensions
{
     public void Update(this State aDifferentStateObject)
     {
        // the world is as it should be
        aDifferentStateObject.StateVar1 = "bang!!!" // compiler error
     }
}

ou un champ de sauvegarde, afin que vous puissiez le définir en interne

public class SomeOtherNonRelatedClass
{
     public void Update(State aDifferentStateObject)
     {
        // the world is as it should be
        aDifferentStateObject.StateVar1 = "bang!!!" // compiler error
     }
}

2 commentaires

L'OP a dit "d'un autre objet de la même classe", pas "d'une autre classe". Vous avez cité cette partie de la question vous-même, mais vous semblez l'avoir mal interprétée.


@IgbyLargeman et ensuite clarifié la règle et les solutions possibles, mais votre commentaire est apprécié et pris



2
votes

Ce n'est peut-être pas la solution la plus directe, mais une façon de protéger les propriétés consiste à utiliser une interface.

public interface IState
{
    string StateVar1 { get; }
}

public class State:IState
{
    //Some example state information
    public string StateVar1 { get; private set; }

    //This method will be farmed out to multiple other threads
    public void Update(IState aDifferentStateObject)
    {
        StateVar1 = "I want to be able to do this";  // Allowed
        string infoFromAnotherObject = aDifferentStateObject.StateVar1; 
        aDifferentStateObject.StateVar1 = "I don't want to be able to do this, but I can"; // NOT allowed
    }
}


2 commentaires

Mais vous pouvez toujours modifier la propriété StateVar1 en faisant simplement référence à l'instance de classe. (aDifferentStateObject as State) .StateVar1 = "" .


@IgbyLargeman oui c'est possible, tant qu'il est accédé en tant qu'instance de classe, vous pouvez y accéder. C'est pourquoi avait dit "pas la solution la plus directe". Cela ne fonctionne que lorsque vous travaillez sur des interfaces. Merci de l'avoir mis en discussion



0
votes

Si vous écrivez un cours, il est supposé que vous ferez fonctionner le cours comme vous le souhaitez. Le but de rendre les choses privées est d'empêcher vos collègues (ou clients) de briser les préoccupations de votre classe pendant qu'ils travaillent sur leurs propres classes / fonctions / modules.
Dire "Je ne veux pas pouvoir faire ça". manque quelque peu le point.

Cela dit, ce qui est bien avec les langages moins permissifs en général, c'est qu'ils empêchent vos collègues d'écrire du code merdique ou non idiomatique. Les autres réponses montrent des idiomes que vous pourriez utiliser qui rendraient plus difficile pour vos pairs de modifier plus tard votre joli motif élégant. Anu Viswan obtient mon vote.


0 commentaires

0
votes

ajoutez le champ this0 = this et dans le setter, vérifiez que this==this0.


1 commentaires

Si vous créez un setter, vous avez besoin d'un champ de sauvegarde. Toutes les instances de la classe peuvent modifier tous les champs de toutes les autres instances.