2 votes

Comment empêcher la fonction get/set d'exposer une propriété locale en Typescript

En Javascript, je peux créer une propriété d'objet avec des méthodes get/set :

function Field(arg){
    var value = arg;

    // Créer une propriété en lecture seule "value"
    Object.defineProperty(this, "value", {           
        get: function () {
            return value;
        },
        set: function () {
            console.log("ne peut pas être défini");
        }
    });
}

var obj = new Field(10);    
console.log(obj.value); // 10
obj.value = 20;         // "ne peut pas être défini"

Définir la propriété value est interdit ici.

En TypeScript, si je veux obtenir le même comportement, je devrais faire ceci (comme suggéré par get and set in TypeScript) :

class Field {
    _value: number;

    constructor(arg) {
        this._value = arg;
    }

    get value() {
        return this._value;
    }

    set value() {
        console.log("ne peut pas être défini");
    }
}

var obj = new Field(10);

console.log(obj.value); // 10
obj.value = 20;         // "ne peut pas être défini"
obj._value = 20;        // POSSIBILITÉ DE CHANGER LA VALEUR !
console.log(obj.value); // 20

Mais le problème est que la prétendue propriété privée _value peut être accédée/changée par l'utilisateur directement sans passer par les méthodes get/set pour value. Comment puis-je empêcher l'utilisateur d'accéder à cette propriété (_value) directement ?

4voto

Anzeo Points 6071

Vous pouvez utiliser Object.defineProperty en TypeScript également.

J'ai modifié votre classe Field comme suit :

class Field{
    value: any;
    constructor(arg: any)
    {
        var value = arg;
        Object.defineProperty(this, "value",{           
            get: () => {
                return value;
            },
            set: function () {
                console.log("cannot set");
            }
        });
    }
}

Notez que vous ne pouvez pas utiliser la valeur définie sur la classe elle-même, sinon le getter du champ serait appelé de manière récursive jusqu'à ce que vous rencontriez une Taille de pile d'appels maximale dépassée. La déclaration value:any sur la définition de classe évite l'erreur du compilateur:

la propriété "value" n'existe pas sur la valeur du type Field

Ensuite, vous pouvez exécuter ce code TypeScript pour obtenir les mêmes résultats que votre exemple de code JavaScript :

var obj = new Field(10);
console.log(obj.value);
obj.value = 20;

1voto

JcFx Points 6266

En TypeScript, il suffit d'ajouter le modificateur private (dans votre exemple, _value est public):

private _value:number;

... le compilateur devrait maintenant vous empêcher de définir la propriété depuis l'extérieur de la classe:

var obj = new Field(10);
obj._value = 20; // Erreur: La propriété '_value' n'existe pas sur le type 'Field'.

Mais cela ne cache pas _value de la même façon dans le JS de sortie. Les membres privés de TypeScript sont privés seulement dans TS. Voir cette réponse et l'intéressante discussion sur codeplex qu'elle pointe.

0voto

Eli TheHuman Points 36

Initialisez-le avec le readonly modificateur.

class Field {
    readonly _value: number;

    constructor(arg) {
        this._value = arg;
    }
}

Permet une implémentation beaucoup plus propre.

-1voto

basarat Points 22425

Si vous ne créez pas de variable, elle ne sera pas accessible :

class Field{
    get value(){
        return 10;
    }

    set value(){
        console.log("ne peut pas être défini");
    }
}

var obj = new Field();
console.log(obj.value); // 10
obj.value = 20;  // ne peut pas être défini
console.log(obj.value); // 10 

Évidemment, je recommanderais de supprimer complètement le set :

class Field{
    get value(){
        return 10;
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X