16.6. Kwalifikowany dostęp chroniony
Pozostała do pokazania trzecia, kwalifikowana postać modyfikatora protected. Metoda speak z klasy Greeting, zdefiniowana w pliku QualifiedProtedted1.scala, jest poprzedzona modyfikatorem private[hello]. To oznacza, że powinna być dostępna w całym pakiecie hello.
Plik QualifiedProtected1.scala: package hello { class Greeting(greeting: String) { private[hello] def speak = println(greeting) } object Hello { def speak = new Greeting("Hello!!!!").speak } }
W pakiecie hello znajduje się jedno odwołanie do tej metody — w definicji obiektu Hello. Ponieważ znajduje się w pakiecie hello, to kompilator kompiluje ten kod bez błędów.
$ scalac QualifiedProtected1.scala $
W pliku QualifiedProtected2.scala znajduje się próba zdefiniowania obiektu Hi, dziedziczącego z klasy Greeting.
Plik QualifiedProtected2.scala: object Hi extends hello.Greeting("Hi!!!!") { def hi = speak }
Obiekt Hi nie kompiluje się, gdyż próbuje uzyskać dostęp do metody speak spoza pakietu hello, co jest niemożliwe.
$ scalac QualifiedProtected1.scala QualifiedProtected2.scala
QualifiedProtected2.scala:2: error: method speak in class Greeting cannot be accessed in object Hi
def hi = speak
^
one error found
Potrzebna jest zmiana kwalifikatora private[hello] na protected[hello] w definicji metody speak. Poprawiona definicja znajduje się w pliku QualifiedProtected3.scala.
Plik QualifiedProtected3.scala: package hello { class Greeting(greeting: String) { protected[hello] def speak = println(greeting) } object Hello { def speak = new Greeting("Hello!!!!").speak } }
Teraz obiekt Hi kompiluje się i można wywołać jego metodę hi.
scala> Hi.hi Hi!!!!
W definicji metody speak kwalifikator [hello] jest potrzebny. Usunięcie go i pozostawienie samego modyfikatora protected powodowałoby błąd kompilacji obiektu Hello. Tak zmodyfikowany przykład znajduje się w pliku QualifiedProtected4.scala.
Plik QualifiedProtected4.scala: package hello { class Greeting(greeting: String) { protected def speak = println(greeting) } object Hello { def speak = new Greeting("Hello!!!!").speak } }
Kod z pliku QualifiedProtected4.scala nie kompiluje się.
$ scalac QualifiedProtected4.scala
QualifiedProtected4.scala:6: error: method speak in class Greeting cannot be accessed in hello.Greeting
Access to protected method speak not permitted because
enclosing object Hello in package hello is not a subclass of
class Greeting in package hello where target is defined
def speak = new Greeting("Hello!!!!").speak
^
one error found
Gdyby z pakietu hello usunąć definicję obiektu Hello, to nie tylko można by się pozbyć kwalifikatora [hello], ale nawet można by go zamienić na kwalifikator [this]. Ilustrują to przykłady w plikach QualifiedProtected5.scala i QualifiedProtected6.scala.
Plik QualifiedProtected5.scala: package hello { class Greeting(greeting: String) { protected def speak = println(greeting) } }
Plik QualifiedProtected6.scala: package hello { class Greeting(greeting: String) { protected[this] def speak = println(greeting) } }
Oba pliki kompilują się poprawnie wraz z plikiem QualifiedProtected2.scala.
$ scalac QualifiedProtected2.scala QualifiedProtected5.scala $ scalac QualifiedProtected2.scala QualifiedProtected6.scala $
![]() | Specyfikacja języka Scala opisuje modyfikator private w punkcie 5.2.1, a modyfikator protected w punkcie 5.2.2. |
Plik QualifiedProtected1.scala:
package hello {
class Greeting(greeting: String) {
private[hello] def speak = println(greeting)
}
object Hello {
def speak = new Greeting("Hello!!!!").speak
}
}

