2017-01-27 5 views
3

В Scala, как я могу расширить признак в классе с private параметр конструктора, определенный в признаке?Расширить черту с параметром частного конструктора

trait Parent { 
    protected def name: String 
    require(name != "", "wooo problem!") 
} 

class Child(private val name: String) extends Parent { 
    println("name is " + name) 
} 

выше класс выдает ошибку:

class Child needs to be abstract, since method name in trait Parent of type ⇒ String is not defined.

Из курса я могу:

  1. сделать Child класса аннотацию,
  2. определить его без использования частного в конструктор, как class Child(val name: String).
  3. сделать Родительскую abstract class вместо признака

Но с вышеприведенной реализацией, не существует никакого способа, я могу иметь частный параметр конструктора, расширяя черту? Обратите внимание, что я хочу, чтобы переменная была закрытой, чтобы я не смог сделать childInstance.name.

+0

Что вы пытаетесь достичь с этим? Зачем нужен конструктор с частной переменной? Не можете ли вы просто определить приватную переменную в классе и иметь пустой конструктор? – nmat

+0

Поскольку этот класс расширяется несколькими детьми, я не хочу повторять код. Я думаю, что нашел способ. Если я сделаю переменную в признаке 'protected' и изменим дочерний конструктор на' Child (name: String) ', я не могу получить доступ к переменной снаружи. Это достаточно хорошо для меня! – rgamber

+0

Почему бы вам просто не задать 'class Child {private val name =" "}'? – nmat

ответ

1

Попробуйте

trait Parent { 
    protected def name: String 
    require(name != "", "wooo problem!") 
    } 

    class Child(override protected val name: String) extends Parent { 
    val publicVar = "Hello World" 
    println("name is " + name) 
    } 

    def main(args: Array[String]): Unit = { 
    val child = new Child("John Doe") 
    println(child.publicVar) 
    println(child.name) // Does not compile 
    } 

Вы не сможете получить доступ к child.name

+0

Как я уже говорил в вопросе, мне нужна переменная ** private **. Так что нет, я не хочу использовать 'override'. – rgamber

+0

Я меняю оба на охрану. Когда я сменил ребенка на личную, он больше не работает. Сообщение об ошибке: класс Ребенок должен быть абстрактным, поскольку имя метода в признаке Родитель типа => Строка не определена –

+0

Я снова обновил код. Я думаю, что пример делает то, что вы хотите: println (child.name) // Не компилируется –

1

Если у вас есть абстрактный метод в черте, то все производные классы должны иметь одинаковые (или более разрешающий) модификатор (в вашем случае как минимум защищенный) для абстрактных методов.

trait Parent { 
    protected def name: String 
    require(name != "", "wooo problem!") 
} 

class Child(private val privateName: String) extends Parent { 
    override protected def name: String = privateName 
    println("name is " + name) 
} 

Вы можете оставить свой конструктор частный, но вы должны определить override protected def name: String и использовать частную стоимость вашего конструктора.