2015-08-10 21 views
5

Secondo la sezione "8.1.1.1" di JLS che abbiamo:ereditarietà dei metodi astratti con accesso pacchetto

Una classe C ha metodi astratti se una delle seguenti condizioni:

• Qualsiasi dei metodi membri (§8.2) di C - dichiarato o ereditato - è astratto.

• Qualsiasi delle superclassi di C ha un metodo astratto dichiarato con accesso pacchetto, e non esistono metodi che l'override del metodo astratto da C o da una superclasse di C

E 'interessante, perché dobbiamo seconda opzione qui. In particolare, perché abbiamo esattamente "accesso al pacchetto". E i metodi "pubblici" o "protetti"?

+0

In pratica si sta dicendo che la classe è astratta finché non si forniscono implementazioni concrete per tutti i metodi astratti (metodi espliciti nella classe o impliciti dalle classi padre). Ricorda: "l'ambito del pacchetto" è quando tu * non * specifichi "pubblico" o "protetto" o "privato"; è visibile ovunque all'interno del pacchetto e non è visibile all'esterno del pacchetto. – paulsm4

risposta

3

Dall'ordine di più privato a più aperti, i modificatori Java vanno:

  • privato pacchetto
  • protetta
  • pubblici

classi figlie non possono ereditare i metodi del pacchetto di una classe genitore in un altro pacchetto. Quindi una classe che eredita da un tale genitore non sarebbe astratta secondo la regola 1. Quindi esiste la seconda regola per affrontare la situazione in cui una classe figlia eredita da un genitore astratto e non è in grado di fornire un'implementazione dei metodi astratti del pacchetto.

È una situazione assurda, e non mi aspetterei mai di vederlo in nessun programma da nessuna parte. Ma il linguaggio deve essere completamente specificato oppure si potrebbe finire con un bug strano che consente di creare una classe con metodi non definiti per l'istanziazione.

0

Il probabile significato di questo è che protected e public sono anche dichiarazioni che forniscono l'accesso al pacchetto. I metodi private non lo sono e non possono essere astratti.

0

Sì, penso che tu abbia ragione. La seconda opzione riguarda solo un caso particolare: la sottoclasse specifica si trova in un pacchetto diverso rispetto alla sua superclasse.

Per esempio,

package superpackage; 

public abstract class SuperFoo { 
    abstract void foo(); 
} 


package subpackage; 

import superpackage.SuperFoo; 

public abstract class SubFoo extends SuperFoo {} 

Si prega di notare che questa classe deve essere dichiarata astratta, altrimenti abbiamo errore di compilazione.

In questo caso particolare non abbiamo "ereditarietà del metodo foo" poiché l'ereditarietà richiede che la classe SubFoo sia nello stesso pacchetto di SuperFoo. vedere la sezione 8.4.8 in JLS per ulteriori dettagli.

Tuttavia, questa classe contiene ancora il metodo "pippo" (per definizione) e quindi dovrebbe essere contrassegnato con una parola chiave astratta.

Inoltre, possiamo estendere la nostra classe SubFoo da un'altra classe concreta che appartiene al pacchetto "superpackage".

Per esempio,

package subclass; 

import subpackage.SubFoo; 

public class SecondSubFoo extends SubFoo { 
    @Override 
    void foo() {} 
} 

Nota:

1) Il fatto è che i metodi pubblici e protetti rientrano in primo elemento di definizione, come sono ereditate e non c'è bisogno secondo elemento di definizione per loro.

2) I metodi di accesso al pacchetto sono anch'essi rientrati nel primo elemento di definizione se sono nello stesso pacchetto e quindi non è necessario un secondo elemento di definizione anche per loro.

3) D'altro canto, i metodi di accesso ai pacchetti presenti nell'altro pacchetto non rientrano nel primo elemento di definizione in quanto non sono ereditati (vedere la definizione di ereditarietà dei metodi astratti nella sezione 8.4.8 di JSL) e quindi sono richiesti secondo elemento di definizione.