2014-10-17 2 views
2

Эта тема обсуждалась ранее, но не была удовлетворительно удовлетворена (на мой взгляд). Рассмотрим следующий код SCALA:scala переопределяет параметры класса

class A(a:Int) { val _a=a } 
class A1(val a:Int) { val _a=a } 

class B(a:Int) extends A(a)     // OK 
class C(val a:Int) extends A(a)    // OK 

class B1(a:Int) extends A1(a)     // OK 
class C1(val a:Int) extends A1(a)    // fails 
class D1(override val a:Int) extends A1(a)  // OK 

Я считаю, что объявление параметра класса, как вал только оказывает влияние на вызов конструктора: параметр копируется вместо передачи ссылки. Однако в каждом случае поле класса выделяется как val. это верно?

Теперь я не понимаю, почему нам нужно переопределить ключевое слово в последней строке. Обратите внимание, что мы не объявляем классы как классы классов, поэтому автоматическое распределение полей не происходит.

Наконец, есть веская причина, по которой кто-то даже хотел бы определить класс типа A1 с параметром класса val ?

Заранее благодарим за все ответы.

ответ

4

Я считаю, что объявление параметра класса, как вал имеет только эффект на вызове конструктора: параметр копируется вместо передачи ссылки. Однако в каждом случае поле класса выделяется в качестве значения. это верно?

Совсем нет.

Если в конструкторе есть val или var, который вызывает объявление val или var с тем же именем в классе и присваивает ему конструктор при его построении. В противном случае в классе все еще может быть создан (private) val, если параметр конструктора используется вне инициализации, то есть в методе.

В классе А1, то _a член действительно бесполезно, потому что если вы пишете

class A1(val a: Int) {} 

это эквивалентно

class A1(someFreshName: Int) {val a = someFreshName} 

Так в C1, вы пытаетесь объявить новый член Церкви , в то время как уже есть один. Следовательно, переопределение. В вашем конкретном случае, как член будет иметь такое же значение, но вы также могли бы сделать (возможно, не очень хорошая идея)

class C1(override val a: Int) extends A1(12) 

Затем новый член a будет иметь параметр конструктора в качестве значения, и предыдущий a будет иметь значение 12 и быть скрытым (но все же код, написанный в A1, получит к нему доступ).

+0

Didier: Хорошо, спасибо, это действительно очищает много путаницы. –

+0

Почему я получаю 'm: m' в' class A1 (val a: Any) {def test = a}; класс C1 (переопределение val a: Any) расширяет A1 (12) {переопределить def toString = s "$ a: $ test"}; println (новый C1 ("m")) '? Что означает, что «А1 получит доступ к нему»? –

Смежные вопросы