2016-04-10 46 views
1

Dart konusundaki anlayışımı test etmek için, yalnızca x ve y bileşenlerini değil, aynı zamanda açısını ve uzunluğunu da depolayan bir 2D değişmez vektör yaptım. Bunlar sadece x ve y değerlerinin oluşturulmasında hesaplanır. Kısa bir süre sonra, final alanlarının başlatıcı listeleri veya this -parametre kısayolu ile ayarlanması gerektiğini fark ettim. this answer'un işaret ettiği gibi, vektörümü x ve y bileşenlerinden oluşturmak için bir fabrika kurucusu kullanmak zorunda kaldım. Fabrika kurucusu daha sonra girişi doğrular ve özel kurucuyu çağırmadan önce uzunluğu ve açıyı hesaplar. Fabrika konstrüksiyon üreticileri nasıl kullanılır?

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); 
} 

Ama const fabrikalar sadece kurucular yönlendirme olabilir, çünkü fabrika yapıcı const gelemedi dikkatimi çekti. Vektörümün yapıcısında kodu olması için kesinlikle bir yol yok mu ve yine de onu const constructor'ları ile değiştirilemez mi? Ve eğer öyleyse, neden?

Ayrıca, değerler geçtiyse hatalar attığımı, ancak varsayılan olarak sıfırladığımdan, aslında başlatıcı listelerini kullanabileceğimi de belirteceğim. Sonra bunu denedik ve yapıcı bir fabrika olmadığı zaman çalışır çıkıyor:

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))); 

Ama en kısa sürede ben o const bulmaya çalışırken, bu başlatıcı listesinde kod içerdiğini söylüyor derlenmeyen zaman sabitleri.

Dartda bulabildiğim tek değişmez vektör, here on GitHub idi ve hiçbir yöntemde, null-vektörler üzerinde bir noktada kırılacak yöntemlere dayanarak, yapıcı parametrelerinde herhangi bir null-validasyon veya hesaplama yapmaz. .

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)); 

Peki benim sonuç olmalıdır: Aynı zamanda zorunlu başlatıcı listesine kötü performans ve tekrarlama sayesinde başka birinden bir birim vektörü oluşturan bir Oluşturucu sahip? Bunu mümkün kılan bir özelliği özledim mi yoksa sadece bu sınıf için const kullanmamı mı bırakmalıyım?

cevap

1

Dart derleme sırasında Dart kodu yürütmez. Bu, const yapıcılarının bir vücuda sahip olmamasının nedenidir ve neden bu sınırlamayı aşmanın başka bir yolu yoktur.

Örnek oluşturulduğunda kod yürütmek istiyorsanız, const'u kullanmayın. Yine de, Dart'ta bu önemli değil. Dilden çıkarmak için tartışmalar bile vardı çünkü faydalar yeterince büyük değil.

+0

Ben de öyle düşündüm. Bu durumda, sadece konstrüksiyondan kurtulacağım, sınıfımı daha az sağlam hale getirecek mantıklı bir şey gibi görünmüyor. –

+1

Örnekleri değişmez hale getirmeye çalışıyorsanız, sınıfın const olması gerekmez, yalnızca veri alanlarını değiştirmenin bir yolu yoktur. –

+1

Evet, bunun farkındayım, sadece const ile optimize etmenin iyi olacağını düşündüm. Ama muhtemelen çok erken optimize etmeye çalışıyorum, şimdi bir oyun yapmalıyım :) –