2011-09-06 13 views
12

Do czego mogę użyć modyfikatora private final w Scali?Używanie prywatnego ostatecznego modyfikatora Scala?

Biorąc pod uwagę poniższy kod:

1| class A { def callFoo = foo; private final def foo = "bar of A" } 
2| class B extends A { private final def foo = "bar of B"} 
3| println((new A()).callFoo) 
4| println((new B()).callFoo) 

Linia 3 i 4 druki:

1| bar of A 
2| bar of A 

Jest zrozumiałe, dlaczego linia 2 nie drukuje bar of B ponieważ istnieją właściwie dwa foo definicje i ten ostatni w B nie zastępuje pierwszego w A. W przeciwnym razie Scala wymagałby modyfikatora override - zamiast modyfikatora.

Dlaczego więc Scala nie zabrania po prostu kombinacji modyfikatorów private final?

Odpowiedz

14

Ok, to jest trudne. Twoje pytanie: "Dlaczego Scala nie zabrania po prostu kombinacji prywatnego finału modyfikatorów?" opiera się na założeniu, że ta kombinacja nie ma zastosowania.

Załóżmy, że masz rację (i jesteś, z wyjątkiem drobnego szczegółu, o którym będzie mowa w dalszej części). Nie jestem kompilatorem, ale z mojego punktu widzenia "po prostu nie daj się" prawdopodobnie nie jest wcale taki prosty (przynajmniej w tym przypadku). I dlaczego ktoś miałby to zrobić? Jakie są kompromisy? Tylko dlatego, że coś nie jest użyteczne, niekoniecznie oznacza, że ​​wyrządza jakąkolwiek szkodę. Po prostu go nie używaj ...

Oto drobny szczegół, który zdaje się pan przeoczyć. Modyfikator private jest modyfikatorem widoczności, co oznacza, że ​​nie jest świadomy jego istnienia. Ale modyfikatory widoczności Scali są nieco bardziej złożone, niż mówią, Java. Załóżmy, że z jakiegokolwiek powodu potrzebujesz kodu pokazanego w poniższym fragmencie kodu, kompilator na to nie pozwoli.

package scope 

class A { 
    def callFoo = foo; 
    private[scope] final def foo = "bar of A" 
} 
class B extends A { 
    private[scope] final def foo = "bar of B" 
} 

object Main extends App { 
    println((new A()).callFoo) 
    println((new B()).callFoo) 
} 

Jest to jeden z błędów dostarczonych przez kompilator: „metoda foo nie może przesłonić końcowy człon”.

Więc proszę bardzo. Scala prostu zabrania tej kombinacji;)

+0

Nie myślałem o dodatkowym zasięgu, jaki może mieć modyfikator. Masz rację, mając definicję prywatną pakietu, 'final' zakazuje jej przesłonięcia. W tym przypadku ma zastosowanie. Ale w przeciwnym razie myślę, że konstrukt językowy bez efektu nie może być legalny. W tym przypadku, jeśli "final" nie uniemożliwia podklasom lub cechom nadpisanie definicji, to nie może być używane w deklaracji. –

+0

@Wskazuj, że powód "ostateczny" nie zapobiega podklasom/cechom przesłaniającym definicję, ponieważ 'prywatny' już temu zapobiegał. "prywatne" elementy nie są widoczne dla podklas, więc nie ma co nadpisywać. Aby to było problemem, programista musiałby wykonać dwa odrębne błędy: 1) próby zastąpienia metody prywatnej i 2) zapomnienia użycia słowa kluczowego 'override'. Tak samo jest w Javie, z tym że Java jest bardziej podatna na błędy, ponieważ adnotacja '@ Override' jest opcjonalna. –

3

I początkowo myślał, że to zapobiec nadrzędne prywatnych metod w klasach zagnieżdżonych, ale najwyraźniej nie:

class A { 
    private final def foo = 0 

    class B extends A { 
    override def foo = 1 
    } 
} 

error: method foo overrides nothing 
      override def foo = 1 
         ^

Może to tylko uproszczenie refaktoryzacji? Więc jeśli masz metodę final, spróbuj ją ustawić jako private i musisz ją znaleźć, aby nie być private, ponieważ w takim przypadku nie utracisz wartości final?

+1

+1 za punkt "zapobieganie złemu refaktoryzacji"! –

3

Adresowanie szersze pytanie,

Więc dlaczego nie po prostu zakazać Scala kombinacji modyfikatorów prywatny końcowych?

To nowa zasada, a przy tym nowy wyjątek. To sprawia, że ​​język jest bardziej złożony i absolutnie nie ma zysku. Dlaczego sprawić, by było bardziej skomplikowane bez ważnego powodu?

To jest to, co robi Java, czego Odersky nie lubi.Aby język stał się bardziej złożony, musi być jakiś zysk.

+2

Język może być bardziej złożony dla parsera/kompilatora, ponieważ musi być świadomy tego wyjątku. Ale z perspektywy użytkownika myślę, że łatwiej jest, gdy ktoś kieruje się kompilatorem. Innym przykładem może być "abstrakcyjna cecha A" a "cecha A". Jaki jest pożytek z wyraźnego stwierdzenia, że ​​dana cecha jest "abstrakcyjna", gdy dotyczy wszystkich cech. –

+0

@Tim Czy uważasz, że użytkownik nie musi używać _learn_ języka _whole_? W końcu to nie tylko kompilator musi obsługiwać regułę - programista musi się tego nauczyć. –

Powiązane problemy