2010-11-11 16 views
11
Hala Scala öğreniyorum

, ama bir şey Scala yöntemler ve alanlar arasındaki çizgiyi bulanıklaştırır olmasıdır. Mesela ben ... böyle bir sınıf inşa edebilirsinizScala Özellikleri Soru

class MutableNumber(var value: Int) 

Burada anahtar yapıcı-argüman var otomatik beni java bir alıcı/setter gibi 'değer' alanını kullanın olanak sağlamasıdır. API etmiyor beri

// require all mutable numbers to be >= 0 
class MutableNumber(private var _value: Int) { 
    require(_value >= 0) 

    def value: Int = _value 
    def value_=(other: Int) { 
     require(other >=0) 
     _value = other 
    } 
} 

istemci tarafında kod sonu yok: Ben kısıtlamaları eklemek istiyorsanız

// use number... 
val num = new MutableNumber(5) 
num.value = 6 
println(num.value) 

, ben örnek-alanların yerine yöntemleri kullanarak geçiş yapabilirsiniz 't değiştirin:

// use number... 
val num = new MutableNumber(5) 
num.value = 6 
println(num.value) 

Benim asmak-up Scala-2,8 eklendi adlı parametreli özelliği ile olduğunu. Ben adında-parametreleri kullanırsanız, benim API değişiklik yapar ve api kırmak yapar.

val num = new MutableNumber(value=5) // old API 
val num = new MutableNumber(_value=5) // new API 

num.value = 6 
println(num.value) 

Bunun için herhangi bir zarif çözüm var mı? MutableNumber sınıfımı nasıl tasarlamalıyım, böylece API'yi kırmadan daha sonra kısıtlamalar ekleyebilirim?

Teşekkürler!

cevap

11

Sen bu durumda sınıfları yapmak aynı numarayı kullanabilirsiniz: Bir arkadaşı nesnesini kullanın.

object Example { 
    class MutableNumber private (private var _value: Int) { 
    require (_value >= 0) 
    def value: Int = _value 
    def value_=(i: Int) { require (i>=0); _value = i } 
    override def toString = "mutable " + _value 
    } 
    object MutableNumber { 
    def apply(value: Int = 0) = new MutableNumber(value) 
    } 
} 

Ve işte çalışan (ve inşa olarak yapıcı özel işaretlenmiş beri, sen kreasyonları için nesneyi kullanması gerekir, gösteren) olan: cevap için

scala> new Example.MutableNumber(5) 
<console>:10: error: constructor MutableNumber cannot be accessed in object $iw 
    new Example.MutableNumber(5) 
^

scala> Example.MutableNumber(value = 2) 
res0: Example.MutableNumber = mutable 2 

scala> Example.MutableNumber() 
res1: Example.MutableNumber = mutable 0 
+0

İlginç içinde herhangi sınıfın tüm üyelerinde değişiklik yapabilir! Bu yüzden kurucuyu gizleyerek herkesi tamamlayıcı nesneyi kullanmaya zorluyorum. Eğer MutableInteger'in kendisini bir vaka sınıfı yapmak istiyorsam?Sınıf tanımının önüne 'case' koyarsam, Scala'nın eşlik eden nesneyi kendim için otomatik olarak oluşturduğunu biliyorum ... bu çözüm hala işe yarayacak mı? – shj

+0

Evet, bir vaka sınıfı için açıkça tanımlanmış bir eşlik nesnesine sahipseniz, o nesnenin üyeleri oluşturulan dosyaya birleştirilir (örneğin, bir tweaked "Companion.apply()" yöntemini sağlamak istiyorsanız, geçersiz kılınabilir) ama autogenerated 'unapply' tutun. –

+0

@shj - Hayır, bu işe yaramaz çünkü vaka sınıfları yapıcı değişkenlerine doğrudan (korumasız) erişmeyi kabul eder. Bunu yapıyorsun çünkü muhafızları istiyorsun (bu durumda 'require (_value> = 0) 'şeklinde). –

2

Teşekkür!

Ne Scala 2.8 Yenilikler: bir kenara olarak, Scala-adamlar bir sorun var farkında olabilir mi Adlandırılan ve Varsayılan Parametreler Şimdiye kadar

... , bağımsız değişken isimleri vardı Kütüphane geliştiricileri için biraz keyfi bir tercihtir ve API'nın önemli bir parçası olarak düşünülmemiştir. Bu aniden değişti, böylece argüman sep daha sonraki bir sürümde ayraç olarak yeniden adlandırıldıysa, mkString (sep = "") yönteminin çağrılması başarısız olur.

Scala 2.9 bu soruna düzgün bir çözüm uygular, ama biz bunun için beklerken isimleri gelecekte değişebilir eğer adıyla delilleri referans dikkatli olun.

+0

Scala 2.9'da düzgün bir çözüm nedir? – vossad01

2
class MutableNumber { 
    private var _value = 0 //needs to be initialized 
    def value: Int = _value 
    def value_=(other: Int) { 
     require(other >=0) //this requirement was two times there 
     _value = other 
    } 
} 

küme parantezi

val n = new MutableNumber{value = 17} 
+0

Bu, parantez kullanan her MutableNumber örneğinin anonim oluşturulmasının dezavantajına sahiptir. –