2013-05-07 21 views
5

Dowiedziałem się, że Scala nie sprawdza definicji obiektów prywatnych (private[this]) lub chronionych obiektami (protected[this]) pod względem ich pozycji różnicowej. Dlaczego nie można ich sprawdzić?Dlaczego nie można sprawdzić definicji obiektów prywatnych lub chronionych obiektami pod kątem ich pozycji różnicowej?

Czytałem materiały związane z tym tematem, ale nie udało mi się znaleźć pełnej odpowiedzi. . Po pierwsze, Odersky i inni w „Programowanie w Scala”, mówi:

http://www.artima.com/pins1ed/type-parameterization.html#19.7

Okazuje się, że dostęp do zmiennych z tego samego obiektu, w którym są zdefiniowane nie powodują problemów z wariancji. Intuicyjne wyjaśnienie polega na tym, że w celu skonstruowania przypadku, w którym wariancja prowadziłaby do błędów typu, trzeba mieć odniesienie do obiektu zawierającego, który ma statycznie słabszy typ niż typ, z którym obiekt został zdefiniowany.

nie jestem pewien dokładnie, co autorzy rozumie przez „obiekt zawierający” i „statycznie słabsze typu”. Przykład kodu byłby tu bardziej pożądany.

Po drugie, "senia" dała dobry przykład w Scala Modifiers and Type parametrization, który pokazuje, jaki problem mogą mieć zmienne class-private (private) z wariancją. Ten przykład przekonuje mnie, dlaczego prywatni członkowie klasy powinni być sprawdzani pod kątem swoich pozycji różnicowych, ale nie dali odpowiedzi na temat przyczyny, dla której nie musimy sprawdzać obiektów - definicje prywatne/chronione. Rozumiem, że takiego kodu, jak getOtherCache(), nie można zapisać z polami obiektowo-prywatnymi. Nie daje jednak dowodu na nieszkodliwość obiektów-prywatnych/rzutowanych definicji, w których nie napisaliśmy programu, którego definicje obiektowo-prywatne/rzutowane powodują problemy z wariancją.

trzecie, Michid wspomniano tematu krótko podczas decsribing sposobu realizacji funkcji memoization w Scala:

http://michid.wordpress.com/2009/02/23/function_mem/

class Memoize1[-T, +R](f: T => R) extends (T => R) { 
    ... 
    private[this] val vals = mutable.Map.empty[T, R] 
    ... 
} 

Jednak od Vals jest dostępne tylko z jego zawierającego instancji, nie może powodować problemy z wariancją.

Niestety nie odpowiada na moje pytanie "jak (lub dlaczego) jest kontrola dostępu związana z wariancją?".

Czy możesz wyjaśnić bardziej szczegółowo powody nie sprawdzania obiektów prywatnych/chronionych definicji dla ich pozycji wariancji (lub podać kilka odniesień)?

Odpowiedz

5

Problemy zmienności wystąpić tylko raz w czasie kompilacji i czasu wykonania typ obiektu różnią:

val a: List[Any] = List("foo"): List[String] 

tutaj a ma statycznie słabszego typu (List[Any]) nie określone (List[String]). Co więcej, to samo dotyczy obiektu zawierającego (tj. Elementu listy). (Statyczny typ Any, określony typ String).

Jeśli mamy pól obiektowych prywatny (lub obiekt chroniony), sytuacja ta nie może wystąpić:

trait A[-T] { 
    protected[this] val x: T 
} 

Gdy mamy dostęp x możemy być pewni, to jest rzeczywiście typu T, nawet jeśli A jest przeciwwskazane -variant, ponieważ odniesienie this nie może być gdzieś przeniesione. (Zawsze w pełni znamy nasz własny typ).

Więc kiedy wrócimy do słów Odersky tu, rzućmy okiem na:

val cont: A[String] = new A[Any] { ... } 
cont.x // BAD! Is `Any`, not `String` 

cont jest odwołaniem do obiektu, który ma statycznie słabszy typ niż określony z, dlatego odniesienie do x jest nie dozwolony. Ta sytuacja rzutowania nie będzie miała miejsca w przypadku tego wskaźnika, dlatego poniższe ustawienie jest OK:

trait B[-T] extends A[T] { 
    def foo() { 
    // here, this has always the most specific type. 
    val tmp: T = this.x 
    // do stuff 
    } 
}