2014-05-14 9 views
22

Przeczytałem section Programowania w Scali, gdzie wprowadzono abstract override, ale nadal jestem zdezorientowany tym, co dokładnie oznacza łączenie tych modyfikatorów. Fragment kodu, w którym te środki modyfikujące służy zostanie wklejony poniżej:Dlaczego "abstrakcyjne zastąpienie" nie wymaga "przesłonięcia" samego w subkategorii?

trait Doubling extends IntQueue { 
    abstract override def put(x: Int) { super.put(2 * x) } 
} 

W szczególności, jestem zdezorientowany celów abstract w tym przypadku i dlatego nie możemy osiągnąć oczekiwane rezultaty po prostu ze słowem kluczowym override. Gdybyśmy nie zawarli połączenia pod numerem super, potrzebowalibyśmy słowa kluczowego abstract? Dlaczego lub dlaczego nie? Poszukuję szczegółowych wyjaśnień tego słowa kluczowego, ponieważ dotyczy to cech, które można układać w stosy.

Odpowiedz

18

Powodem jest to, że metoda klasy bazowej jest streszczenie

abstract class IntQueue { 
    def get(): Int 
    def put(x: Int) 
} 

Jeśli było nie umieścić abstract na cechy skończyć z wyjaśnieniem Ci szukali:

trait Doubling extends IntQueue { 
    override def put(x: Int) { super.put(2 * x) } 
} 
<console>:9: error: method put in class IntQueue is accessed from 
super. It may not be abstract unless it is overridden by a member 
declared `abstract' and `override' 
      override def put(x: Int) { super.put(2 * x) } 

Musisz więc oznaczyć metodę jako abstract.

Oto „druga strona” równania: czy metody mają implementacje to nie jest konieczne, aby oznaczyć metodę, trait „s jako abstract:

abstract class IntQueue { 
    import collection.mutable._ 
     val q = Queue[Int]() 
     def get(): Int = { q.dequeue() } 
     def put(x: Int) = { q.enqueue(x) } 
    } 

jest teraz konieczne włączenie abstract

trait Doubling extends IntQueue { 
     /* Look Ma! no abstract here ! */ override def put(x: Int) { super.put(2 * x) } 
     } 
defined trait Doubling 
+1

_Thank you_. Z jakiegoś powodu ciągle widzę przykłady sztaplowania, które można zestawiać z 'abstrakcyjnym przesłonięciem ', ale wydaje mi się, że te dwie koncepcje są faktycznie oddzielne (chociaż oba opierają się na dynamicznie związanym" super "). – Max

5

Chodzi o to, że jest to niepełna korekcja - nadal chcesz wymagają ostatecznie konkretną realizację cechy, aby zapewnić tę metodę, choć jesteś modyfikowanie tego hypotheti zachowanie metody cal. Innymi słowy, metoda, którą nadpisujesz, nie jest pełną, samodzielną implementacją. Daje podobny efekt, co potęga method decorator w Pythonie.

O ile mogę rozumieć, sposób na cecha jest abstract override wtedy i tylko wtedy, gdy wymaga to super, ale przerywa hermetyzacji oczekiwać klienta kodu do kontroli wdrażania metody wiedzieć potrzebuje betonu realizacja. Dlatego należy go oznaczyć jako abstract override, aby w pełni zdefiniować interfejs.

2

Część stanowisk late binding in scala traits; zapewnia bardzo jasne wyjaśnienie; podana w przybliżeniu poniżej (przeczytaj full post, aby uzyskać więcej informacji):

Streszczenie klasy bazowej zapewnia implementację metody requestApproval. Jest to dobre, ponieważ lewostronna cecha nazywa tę metodę. Co się dzieje, jeśli metoda klasy bazowej jest abstrakcyjna?

abstract class ApprovalRequest { 
    def requestApproval() 
} 

Jeśli zmienimy tego, mamy dość dziwną wiadomość od kompilatora: błąd: metoda requestApproval w klasie ApprovalRequest jest dostępne z Super.Może nie być abstrakcyjny, o ile nie zostanie zastąpiony przez element zadeklarowany jako abstract i override Kombinacja abstract i override mówi kompilatorowi, że ostateczna implementacja metody zostanie zapewniona przez łączenie klas w tę cechę. Jeśli dodamy słowo kluczowe abstract do metod, nie będziemy mogli już korzystać z naszej anonimowej implementacji ApprovalRequest. Ten obiekt nie może zostać utworzony, ponieważ metody abstrakcyjnego zastępowania będą szukały implementacji o wartości requestApproval. Zamiast tego musimy stworzyć nową klasę, która rozszerza ApprovalRequest i implementuje requestApproval. Następnie łączymy cechy w instancję tej klasy.

class ApprovalDelegate extends ApprovalRequest { 
    override def requestApproval() { 
    println("and now we play the waiting game") 
    } 
} 

val adCampaign = new ApprovalDelegate with MarketingApprovalRequest 
    with FinanceApprovalRequest with ExecutiveApprovalRequest 

który będzie teraz dać wyjście:

requesting approaval from executives 
requesting approval from Finance 
requesting approval from Marketing 
and now we play the waiting game