2016-04-10 16 views
1

Um mein Verständnis von Dart zu testen, habe ich einen 2D unveränderlichen Vektor erstellt, der nicht nur seine x- und y-Komponenten, sondern auch seinen Winkel und seine Länge speichert. Sie werden nur bei der Konstruktion aus den x- und y-Werten berechnet. Ich erkannte bald, dass endgültige Felder mit Initialisierungslisten oder der this -Parameterverknüpfung gesetzt werden müssen, die nicht viel berechnete Werte erlauben. Wie this answer weist darauf hin, ich musste einen Factory-Konstruktor verwenden, um meinen Vektor aus seinen X- und Y-Komponenten zu erstellen. Der Factory-Konstruktor validiert dann die Eingabe und berechnet die Länge und den Winkel vor dem Aufruf des privaten Konstruktors.Wie verwenden Sie Factory Const Konstruktoren?

import 'dart:math'; 

class ImmutableVector { 

    // private fields 
    final double _x; 
    final double _y; 
    final double _angle; 
    final double _length; 

    // getters 
    double get x => _x; 
    double get y => _y; 
    double get angle => _angle; 
    double get length => _length; 

    /// Constructs a vector out of cartesian components. 
    /// 
    /// Converts both arguments to doubles. 
    /// Null values will be treated as zeroes. 
    factory ImmutableVector.xy(num x, num y) { 

    x ??= 0.0; 
    y ??= 0.0; 
    x = x.toDouble(); 
    y = y.toDouble(); 
    var angle = atan2(y, x) % (2*PI); 
    var length = sqrt(pow(x, 2) + pow(y, 2)); 

    return new ImmutableVector._raw(x, y, angle, length); 
    } 

    /// Constructs a vector by setting the fields directly. 
    const ImmutableVector._raw(this._x, this._y, this._angle, this._length); 
} 

Aber es kam zu meiner Aufmerksamkeit, dass ich den Fabrikbauer const nicht machen konnte, weil const Fabriken Konstruktoren nur umleiten können. Gibt es überhaupt keine Möglichkeit, meinem Vektor Code in seinem Konstruktor zu geben und ihn immer noch mit Konst-Konstruktoren unveränderbar zu machen? Und wenn ja, warum?

Ich werde auch erwähnen, dass ich Fehler geworfen habe, wenn die übergebenen Werte Null waren, aber ich habe es standardmäßig auf Null gesetzt, so dass ich tatsächlich Initialisierungslisten verwenden konnte. Ich habe dann versucht, dies zu tun, und stellt sich heraus, es funktioniert, wenn der Konstruktor keine Fabrik ist:

ImmutableVector.xy(num x, num y) : this._raw(
     x = (x ?? 0.0).toDouble(), 
     y = (y ?? 0.0).toDouble(), 
     atan2(y, x) % (2*PI), 
     sqrt(pow(x, 2) + pow(y, 2))); 

Aber sobald ich versuche, es const zu machen, es sagt mir, dass der Code in der Initialisiererliste enthält Nicht-Kompilierzeit-Konstanten. Der einzige unveränderliche Vektor, den ich im Dart finden konnte, war here on GitHub, und er führt keinerlei Nullvalidierung oder Berechnung von Konstruktorparametern durch und verlässt sich ausschließlich auf die Tatsache, dass Methoden irgendwann auf Nullvektoren brechen . Es hat auch einen Konstruktor, der einen Einheitsvektor erzeugt aus einem andere mit einem schlechten Leistung und Wiederholung dank der obligatorischen Initialisiererliste:

const Vector.unit(final num x, final num y, final num z) : 
    this(x/PMath.len(x, y, z), y/PMath.len(x, y, z), z/PMath.len(x, y, z)); 

Also, was soll meine Schlussfolgerung sein? Habe ich eine Funktion vermisst, die das möglich macht, oder sollte ich einfach aufgeben, const für diese Klasse zu verwenden?

Antwort

1

Dart führt beim Kompilieren keinen Dart-Code aus. Dies ist der Grund, warum const Konstruktoren keinen Körper haben können und warum es keine andere Möglichkeit gibt, diese Einschränkung zu umgehen.

Wenn Sie beim Erstellen einer Instanz Code ausführen möchten, verwenden Sie einfach const nicht. Const ist in Dart sowieso nicht so wichtig. Es gab sogar Diskussionen, um es aus der Sprache zu entfernen, weil die Vorteile nicht groß genug sind.

+0

Ich dachte schon. In diesem Fall werde ich einfach const los, was meine Klasse weniger robust macht, scheint nicht logisch zu sein. –

+1

Wenn Sie versuchen, die Instanzen unveränderlich zu machen, muss die Klasse nicht const sein, Sie haben einfach keine Möglichkeit, ihre Datenfelder zu ändern. –

+1

Ja, ich bin mir dessen bewusst, ich dachte nur, es wäre schön, mit const zu optimieren. Aber ich versuche wahrscheinlich zu früh zu optimieren, ich sollte jetzt stattdessen ein Spiel machen :) –