943 Stimmen

get und set in TypeScript

Ich versuche, Get- und Set-Methode für eine Eigenschaft zu erstellen:

private _name: string;

Name() {
    get:
    {
        return this._name;
    }
    set:
    {
        this._name = ???;
    }
}

Wie lautet das Schlüsselwort, um einen Wert zu setzen?

15 Stimmen

Der Unterstrich und PascalCase sind im Konflikt mit den TypeScript-Codierungsrichtlinien: github.com/Microsoft/TypeScript/wiki/Coding-guidelines

4 Stimmen

Hallo @NielsSteenbeek - wenn Sie den TypeScript-Richtlinien für Mitwirkende folgen, würden Sie mit Properties und Backing-Feldern mit einem Namenskonflikt enden. Was ist der vorgeschlagene Ansatz?

1 Stimmen

Vielleicht: typescript privater name: string; getName() { get: {return this.name;} set: {this.name = ???;} }

1465voto

Ezward Punkte 16382

TypeScript verwendet die Getter/Setter-Syntax, die der ECMAScript4/ActionScript3 ähnelt.

class foo {
    private _bar: boolean = false;
    get bar(): boolean {
        return this._bar;
    }
    set bar(value: boolean) {
        this._bar = value;
    }
}

Um sie überhaupt verwenden zu können, müssen Sie sicherstellen, dass der TypeScript-Compiler auf ECMAScript5 oder höher abzielt. Wenn Sie den Befehlszeilencompiler ausführen, verwenden Sie die --target-Flag so:

tsc --target ES5

Wenn Sie Visual Studio verwenden, müssen Sie Ihre Projektdatei bearbeiten, um die Flagge zur Konfiguration des TypeScriptCompile-Build-Tools hinzuzufügen. Sie können dies hier sehen:

Dadurch wird dieser JavaScript-Code erzeugt, der das ECMAScript 5-Feature Object.defineProperty() verwendet.

var foo = (function () {
    function foo() {
        this._bar = false;
    }
    Object.defineProperty(foo.prototype, "bar", {
        get: function () {
            return this._bar;
        },
        set: function (value) {
            this._bar = value;
        },
        enumerable: true,
        configurable: true
    });
    return foo;
})();

Aktuellere Versionen von EcmaScript erzeugen Code, der mehr wie das Original TypeScript aussieht. Wenn beispielsweise EcmaScript2017 als Ziel festgelegt ist, wird folgendes erzeugt:

"use strict";
class foo {
    constructor() {
        this._bar = false;
    }
    get bar() {
        return this._bar;
    }
    set bar(value) {
        this._bar = value;
    }
}

Um sie zu verwenden,

var myFoo = new foo();
if(myFoo.bar) {         // ruft den Getter auf
    myFoo.bar = false;  // ruft den Setter auf und übergibt false
}

Wie @DanFromGermany unten vorschlägt, wenn Sie einfach eine lokale Eigenschaft wie foo.bar = true lesen und schreiben, ist ein Setter- und Getter-Paar übertrieben. Sie können sie jederzeit später hinzufügen, wenn Sie etwas machen müssen, z.B. ein Logging, wann die Eigenschaft gelesen oder geschrieben wird.

Getter können verwendet werden, um schreibgeschützte Eigenschaften zu implementieren. Hier ist ein Beispiel, das auch zeigt, wie Getter mit schreibgeschützten und optionalen Typen interagieren.

//
// Typ mit optionaler schreibgeschützter Eigenschaft.
// baz?:string ist das gleiche wie baz:string|undefined
//
type Foo = {
    readonly bar: string;
    readonly baz?: string;
}
const foo:Foo = {bar: "bar"}
console.log(foo.bar) // gibt 'bar' aus
console.log(foo.baz) // gibt undefined aus

//
// Schnittstelle mit optionaler schreibgeschützter Eigenschaft
//
interface iFoo {
    readonly bar: string;
    readonly baz?: string;
}

const ifoo:iFoo = {bar: "bar"}
console.log(ifoo.bar)  // gibt 'bar' aus
console.log(ifoo.baz)  // gibt undefined aus

//
// Klasse implementiert bar als Getter,
// lässt aber baz weg.
//
class iBarClass implements iFoo {

    get bar() { return "bar" }
}
const iBarInstance = new iBarClass()
console.log(iBarInstance.bar) // gibt 'bar' aus
console.log(iBarInstance.baz) // gibt 'undefined' aus
// Zugriff auf baz gibt Warnung aus, dass baz nicht auf iBarClass existiert, gibt aber undefined zurück
// beachten Sie, dass Sie baz als Getter definieren könnten
// und einfach undefined zurückgeben, um die Warnung zu entfernen.

//
// Klasse implementiert eine optionale schreibgeschützte Eigenschaft als Getter
//
class iBazClass extends iBarClass {
    private readonly _baz?: string

    constructor(baz?:string) {
        super()
        this._baz = baz
    }

    get baz() { return this._baz; }
}

const iBazInstance = new iBazClass("baz")
console.log(iBazInstance.bar)  // gibt bar aus
console.log(iBazInstance.baz)  // gibt baz aus

74 Stimmen

Schöne Antwort. Beachten Sie auch, dass im Gegensatz zu C# Eigenschaften in TypeScript (v0.9.5) derzeit nicht virtualisiert sind. Wenn Sie "get bar()" in einer abgeleiteten Klasse implementieren, ersetzen Sie "get bar()" in der Elternklasse. Implikationen sind, dass Sie nicht in der Lage sind, den Basisklassen-Zugriff von dem abgeleiteten Zugriff aus aufzurufen. Dies gilt nur für Eigenschaften - Methoden verhalten sich wie erwartet. Siehe Antwort von SteveFenton hier: stackoverflow.com/questions/13121431/…

17 Stimmen

Ich bin etwas verwirrt über den Unterstrich. Die TypeScript-Konvention besagt, dass keine Unterstriche für private Variablen verwendet werden sollen? Aber in diesem Fall müssen wir Unterstriche verwenden - oder wir bekommen einen Konflikt zwischen der privaten und öffentlichen "bar"

4 Stimmen

Verwenden Sie den Unterstrich als persönliche Präferenz für private Eigenschaften. Ich glaube jedoch, dass Sie recht haben, dass wir möchten, dass die Eigenschaft einen anderen Namen als die Getter-/Setter-Methoden hat.

157voto

TornadoAli Punkte 1877

Ezward hat bereits eine gute Antwort gegeben, aber ich habe bemerkt, dass einer der Kommentare fragt, wie es verwendet wird. Für Leute wie mich, die auf diese Frage stoßen, dachte ich, es wäre nützlich, einen Link zur offiziellen Dokumentation über Getter und Setter auf der Typescript-Website bereitzustellen, da das gut erklärt, hoffentlich immer auf dem neuesten Stand bleibt und Beispielnutzung zeigt:

http://www.typescriptlang.org/docs/handbook/classes.html

Insbesondere für diejenigen, die nicht vertraut sind, beachten Sie, dass Sie das Wort 'get' nicht in einen Aufruf eines Getters einbeziehen (und ähnlich für Setter):

var myBar = myFoo.getBar(); // falsch    
var myBar = myFoo.get('bar');  // falsch

Sie sollten einfach dies tun:

var myBar = myFoo.bar;  // korrekt (get)
myFoo.bar = true;  // korrekt (set) (false ist offensichtlich auch korrekt!)

gegeben eine Klasse wie:

class foo {
  private _bar:boolean = false;

  get bar():boolean {
    return this._bar;
  }
  set bar(theBar:boolean) {
    this._bar = theBar;
  }
}

wird dann der 'bar' Getter für die private '_bar' Eigenschaft aufgerufen.

1 Stimmen

Wenn ich ein öffentliches Klassen-Level-Variable durch eine Eigenschaft ersetzen möchte, handelt es sich dann um einen einfachen Austausch, den ich einfach vornehmen kann, ohne mich zu sorgen? Mit anderen Worten, wenn ich einen Zugriff und einen Setter einer Regressionstest unterziehe, kann ich es als erfolgreich betrachten? Oder gibt es Fälle, in denen es nicht genau so funktioniert wie eine Variable und ich alle 100 Stellen testen muss, die diese Variable/Eigenschaft verwenden?

2 Stimmen

Ich habe mich gefragt, ob es einen Workaround für die Verwendung von Unterstrichen gibt, um den Eigenschaftsnamen von den Getter- oder Setter-Methoden zu unterscheiden. In einem Kurs, den ich besucht habe, hieß es, dass Unterstriche nicht bevorzugt werden, aber es wurde keine Alternative genannt.

3 Stimmen

@cham Du musst hier keine Unterstriche verwenden... Du kannst die private Variable auch notbar nennen, wenn du möchtest.

76voto

Brian Terlson Punkte 9180

Hier ist ein funktionierendes Beispiel, das Sie in die richtige Richtung weisen sollte:

class Foo {
    _name;

    get Name() {
        return this._name;
    }

    set Name(val) {
        this._name = val;
    }
}

Getter und Setter in JavaScript sind einfach normale Funktionen. Der Setter ist eine Funktion, die einen Parameter benötigt, dessen Wert der gesetzte Wert ist.

35 Stimmen

Um es klarzustellen, es ist nicht erforderlich, dass die Eigenschaft, der Getter und der Setter static sind.

1 Stimmen

Die Variablenverweise sind jedoch immer noch statisch. Foo._name sollte durch this._name ersetzt werden

9voto

k33g_org Punkte 524

Sie können dies schreiben

class Human {
    private firstName : string;
    private lastName : string;

    constructor (
        public FirstName?:string, 
        public LastName?:string) {

    }

    get FirstName() : string {
        console.log("Hole Vorname : ", this.firstName);
        return this.firstName;
    }
    set FirstName(value : string) {
        console.log("Setze Vorname : ", value);
        this.firstName = value;
    } 

    get LastName() : string {
        console.log("Hole Nachname : ", this.lastName);
        return this.lastName;
    }
    set LastName(value : string) {
        console.log("Setze Nachname : ", value);
        this.lastName = value;
    } 

}

2 Stimmen

Warum das öffentliche im Konstruktor?

20 Stimmen

Ja, kann kein public im Konstruktor in diesem Code haben. public definiert hier doppelte Elemente.

4 Stimmen

Du kannst es schreiben, aber es wird nicht kompiliert werden.

5voto

Willem van der Veen Punkte 26043

TS bietet Getter und Setter, die es Objekteigenschaften ermöglichen, mehr Kontrolle darüber zu haben, wie sie zugegriffen werden (Getter) oder aktualisiert werden (Setter) außerhalb des Objekts. Anstelle direkt auf die Eigenschaft zuzugreifen oder sie zu aktualisieren, wird eine Proxy-Funktion aufgerufen.

Beispiel:

class Person {
    constructor(name: string) {
        this._name = name;
    }

    private _name: string;

    get name() {
        return this._name;
    }

    // Überprüft zunächst die Länge des Namens und aktualisiert dann den Namen.
    set name(name: string) {
        if (name.length > 10) {
            throw new Error("Name hat eine maximale Länge von 10");
        }

        this._name = name;  
    }

    doStuff () {
        this._name = 'foofooooooofoooo';
    }

}

const person = new Person('Willem');

// wirft keine Fehlermeldung, Setter-Funktion wird nicht aufgerufen, wenn this._name in der Objektmethode geändert wird
person.doStuff();  

// wirft einen Fehler, weil der Setter aufgerufen wird und der Name länger als 10 Zeichen ist
person.name = 'barbarbarbarbarbar';

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X