2016-06-02 5 views
2

Я не часто использую наследование, поэтому я не уверен, почему он не работает. В моем проекте у меня есть следующие вещи:Доступ к защищенному члену базового класса

Базовых запечатанный класс с защищаемым элементом:

sealed class TheRoot { 
    protected def some: String = "TheRoot" 
} 

И это потомок с некоторой логикой:

final case class Descendant() extends TheRoot { 
    def call: Unit = { 
    val self: TheRoot = this 
    self.some // <<- throw compilation error 
    } 
} 

Compiling выше дает мне следующую ошибку:

error: method some in class TheRoot cannot be accessed in TheRoot 
Access to protected method some not permitted because 
prefix type TheRoot does not conform to 
class Descendant where the access take place 
      self.some 

Я не совсем уверен, в чем проблема вызова защищенного член из класса супер ... Но это становится все более интересным, если мы обернуть его в объект компаньон, она волшебным образом исправляет проблему:

sealed class TheRoot { 
    protected def some: String = "TheRoot" 
} 

object TheRoot { 
    final case class Descendant() extends TheRoot { 
    def call: Unit = { 
     val self: TheRoot = this 
     self.some // <<- NO ERROR! 
    } 
    } 
} 


// Exiting paste mode, now interpreting. 

defined class TheRoot 
defined object TheRoot 

ответ

1

Как descripted в document

Access to protected members is also a bit more restrictive than in Java. In Scala, a protected member is only accessible from subclasses of the class in which the member is defined. In Java such accesses are also possible from other classes in the same package. In Scala, there is another way to achieve this effect, as described below, so protected is free to be left as is. The example shown illustrates protected accesses:

package p { 
    class Super { 
    protected def f() { println("f") } 
    } 
    class Sub extends Super { 
    f() 
    } 
    class Other { 
    (new Super).f() // error: f is not accessible 
    } 
} 

В ваш код, если вы измените self.some на some, все будет в порядке.

в то время как объект компаньона может получить доступ к любым членам своего компаньона класса, поэтому Descendant объекта TheRoot может получить доступ к защищенному методу some

+0

мне нужно преобразовывать тип текущего объекта, мой пример упрощен. В вашей цитате вы также имеете «защищенный член доступен только из подклассов класса», вот почему я спрашиваю, для меня «потомок» является подклассом «TheRoot». Я знаю механику сопутствующих объектов, но мне непонятно, почему она разрешает защищенный доступ в этом случае. – 4lex1v

+0

Зачем вам нужно пересказывать 'this' в супертип? Вы можете использовать подтип в любом месте, которое принимает подтип (за исключением контравариантных аргументов, конечно) ... Во всяком случае, просмотр вашего защищенного члена в охватывающий пакет ('protected [p] def some: String = ...') также должен работайте как ваш пример с приложением 'Descendant' в объекте. – Sergey

+0

@ 4lex1v Извините, я неправильно понял ваш вопрос раньше. Я нашел еще одну странную вещь. это работает, но сам. – Jerry

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

  • Нет связанных вопросов^_^