2010-09-22 14 views
19

Java ile yazılmış şu sınıfı düşünün ona.Scala sınıf üyeleri ve yapıcı parametreleri adı çatışması

Scala'da buna benzer bir şey yazmak istiyorum.

class NonNegativeDouble(value: Double) { 
    def value = Math.abs(value) 
} 

Ancak derleyici şikayet: İlk başta, güvenilir hatası: aşırı yöntem değeri ihtiyaçları tip

Açıkçası derleyici yöntemi tanımlanan için ifade Math.abs(value) içindeki ifade value gelir düşünmektedir neden . Bu nedenle, tanımlanan yöntem tekrarlayıcıdır, bu yüzden dönüş türünü belirtmem gerekiyor. Bu yüzden, yazdığım kod yapmamı beklediğim şeyi yapmıyor: value'un içinde value yapıcı parametresine başvurmasını ve tanımlanmakta olan yönteme başvurmamasını istedim. Derleyici, Math.abs(this.value) için örtülü olarak eklenmiş gibi. Oluşturucu parametresine val veya var (veya private ... türevleri) eklemek yardımcı olmuyor gibi görünmektedir.

Yani, sorum şu: Ben yapıcı parametre olarak aynı adı taşıyan bir özellik tanımlamak, ama belki farklı bir değer olabilir? Öyleyse nasıl? Değilse neden?

Teşekkürler!

cevap

16

Hayır, yapamazsınız. Scala'da, yapıcı parametreleri özellikleridir, bu nedenle bunları yeniden tanımlamanın bir anlamı yoktur. Böyle Kullanılan

class NonNegativeDouble(initValue: Double) { 
    val value = Math.abs(initValue) 
} 

, initValue oluşturulan örneklerini parçası olmayacaktır:

çözüm, doğal olarak, başka bir isim kullanmaktır. Ancak, bir def veya desen eşleşmesi bildiriminde kullanırsanız, sınıfın her örneğinin bir parçası olur.

+8

Bir kurucu, bir durum sınıfı veya val veya var ile ek açıklama yapılmadıkça bir özellik yapılmaz. Yine de sınıf tanımının içinde herhangi bir yerde kullanılabilir. –

+1

Bu gibi durumlarda yapıcı parametrelerinin herhangi bir adlandırma kuralı var mı? –

+2

@Bruno - Birkaç adlandırma kuralı vardır; Ben şahsen 0 adının eklendiğini beğendim, çünkü bu sıfır bir başlangıç ​​noktası anlamına gelir ve bu kısadır. (Altçizgiler bazen önceden hazırlanır veya eklenir, fakat ben şahsen kendimi etrafta yatan bol altçizgi olduğunu hissediyorum.) –

2

Sen It

class NonNegativeDouble(val value: Double, private val name: String){ 
    if (value < 0) throw new IllegalArgumentException("value cannot be negative") 
    override def toString = 
    "NonNegativeDouble(value = %s, name = %s)" format (value, name) 
} 

val tom = "Tom" 
val k = -2.3 

val a = new NonNegativeDouble(k.abs, tom) 
a: NonNegativeDouble = NonNegativeDouble(value = 2.3, name = Tom) 

a.value 
res13: Double = 2.3 

a.name 
<console>:12: error: value name in class NonNegativeDouble cannot be accessed in NonNegativeDouble 
    a.name 

val b = new NonNegativeDouble(k, tom) 
java.lang.IllegalArgumentException: value cannot be negative 
... 

aynı isimleri "değeri", "isim" ile alan ve parametreyi tanımlayan parametrik sahadan düşünebilirsiniz. Sen ... bu tür özel olarak değiştiriciler ekleyebilirsiniz

+1

"Parametrik alan" ile ne demek istiyorsun? Ve örneğinizde, .value aslında negatif çifte dönecek olan 'NonNegativeDouble' öğesini kolayca başlatabiliriz. – Rogach

+0

@Rogach "parametrik alanlar" ile, kurucudaki parametre adları ile aynı isimlere sahip alanlar oluşturabilirsiniz. Örneğimi geliştirdim. –

4

@Daniel C. Sobral

class NonNegativeDouble(initValue: Double) { 
    val value = Math.abs(initValue) 
} 

kodunuzu doğru olmakla birlikte, "yapıcı parametreleri özellikleridir", bu doğru değildir.

A post from the official site said,

A parameter such as class Foo(x : Int) is turned into a field if it is referenced in one or more methods

Ve Martin'in cevap onun gerçeği doğrulamaktadır: biz hala normal bir yöntem parametresi olarak birincil yapıcı parametreleri tedavi edebilir, ancak parametrelerin herhangi biri tarafından başvuruda bulunulan zaman, Yani normalde

That's all true, but it should be treated as an implementation technique. That's why the spec is silent about it.

yöntemlerden derleyici, akıllıca özel bir alana dönüşecektir.

Değerin önüne herhangi bir resmi parametre atanırsa, derleyici otomatik olarak bir alıcı tanımı oluşturur. Varsa, ek olarak bir ayarlayıcı oluşturur. Dil değerlendirme bölümüne bakın 5.3.

Bu, birincil kurucu parametreleriyle ilgilidir. case classes durumunda

0

olması gerektiği:

case class NonNegativeDouble(private val initValue: Double) { 
    val value = Math.abs(initValue) 
    def copy(value: Double = this.value) = NonNegativeDouble(value) 
} 

copy uygulanması initValue argüman bağlayacak derleyici sintesized sürümünü engellemek için gereklidir.

Derleyicinin, initValue için «fazladan alanı» kullanmayacak kadar akıllı olduğunu umuyorum. Bu davranışı doğrulamadım.

İlgili konular