Java: Sostituzione variabile statica della classe padre?

Ho il seguente classe che sto utilizzando come base di tutti i modelli nel mio progetto:

public abstract class BaseModel
{
    static String table;
    static String idField = "id";       

    public static boolean exists(long id) throws Exception
    {
        Db db = Util.getDb();
        Query q = db.query();
        q.select( idField ).whereLong(idField, id).limit(1).get(table);

        return q.hasResults();
    }

    //snip..
}

Sto quindi cercando di estendere, in modo seguente:

public class User extends BaseModel
{
    static String table = "user";
    //snip
}

Tuttavia, se provo a effettuare le seguenti operazioni:

if ( User.exists( 4 ) )
   //do something

Quindi, piuttosto che la query: "SELECT id FROM user WHERE id = ?", sta producendo la query: “SELECT id from null WHERE id = ?”. Così, il superamento dei table campo in User classe non sembra avere alcun effetto.

Come faccio a superare questo? Se ho aggiunto un setTable() metodo per BaseModel, e chiamato setTable() nel costruttore di User, quindi il nuovo valore di table essere disponibile per tutti i metodi di User classe?

 

3 Replies
  1. 16

    Non è possibile eseguire l’override dei metodi statici o campi di qualsiasi tipo in Java.

    public class User extends BaseModel
    {
        static String table = "user";
        //snip
    }

    Questo crea un nuovo campo User#table che guarda caso ha lo stesso nome BaseModel#table. L’Ide si avvisa che.

    Se si modifica il valore del campo in BaseModel, sarà applicato a tutte le altre classi del modello pure.

    Un modo è quello di avere i metodi di base generico

    protected static boolean exists(String table, long id) throws Exception
    {
        Db db = Util.getDb();
        Query q = db.query();
        q.select( idField ).whereLong(idField, id).limit(1).get(table);
    
        return q.hasResults();
    }

    e utilizzarlo nella sottoclasse

    public static boolean exists(long id)
    {
        return exists("user", id);
    }

    Se si desidera utilizzare il campo di approccio, è necessario creare un BaseDAO classe e hanno una UserDAO (uno per ogni classe del modello) che imposta il campo di conseguenza. Quindi si crea singleton istanze di tutti i tao.

    • Perché sarebbe un IDE in guardia circa i dati di nascondere?
    • Ho esteso la mia risposta.
    • exists() è solo un esempio ,ho un altro 10-20 tali metodi di supporto. Non voglio sovraccaricare tutti, vorrei cambiare solo il nome della tabella di proprietà così tanto.
    • perché causa un comportamento imprevisto, come in OP caso.
    • È assolutamente un comportamento atteso. E ‘ solo che OP non mi aspettavo che. OP sta parlando di sovrascrivere i campi, che non viene mai fatto. Non anche, per esempio, il campo.
    • stackoverflow.com/questions/685300/…
    • “OP non ha previsto che” in modo inaspettato 😉 … inoltre, che downvoted la mia risposta? Almeno dare qualche motivo, vigliacco!
    • stackoverflow.com/questions/1448092/…
    • C’è un modo per controllare dall’interno BaseModel.exists(), quali il tipo di istanza della classe è? E. g utilizzando getClass().getName() o instance of? Quindi, se ho potuto fare if .. instance of User table = "user" .

  2. 9

    Perché Java non permette di sovrascrivere static membri, è fondamentalmente bisogno di ricorrere a un po ‘ più prolisso, ma nel complesso più bello singleton pattern, in cui si sta ancora concettualmente scrittura “statica” del codice, ma tu sei tecnicamente usando (globale/singleton/”statico”) le istanze, in modo da non siete limitati da static.

    (si noti che è necessario utilizzare metodi, perché i campi non partecipare polimorfismo, e quindi non può essere sottoposto a override)

    public abstract class BaseTable {
        public abstract String table();
        public String idField() { return "id"; }
    
        public boolean exists(long id) {
            //don't build queries this way in real life though!
            System.out.println("SELECT count(*) FROM " + table() + " WHERE " + idField() + " = " + id);
            return true;
        }
    }
    
    public class UserTable extends BaseTable {
        public static final User INSTANCE = new UserTable();
        private UseTabler() {}
    
        @Override public String table() { return "user"; }
    }
    
    public class PostTable extends BaseTable {
        public static final Post INSTANCE = new PostTable();
        private PostTable() {}
    
        @Override public String table() { return "post"; }
    }
    
    public static void main(String[] args) {
        UserTable.INSTANCE.exists(123);
        PostTable.INSTANCE.exists(456);
    }

    Uscite:

    SELECT count(*) FROM user WHERE id = 123
    SELECT count(*) FROM post WHERE id = 456
    • ecco come sarebbe simile in Scala con alcuni ingenua riflessione aggiunti, senza il singleton standard: pastebin.com/3iujwygZ
  3. 3

    Per fare ciò che si sta cercando di fare, non fare table statico nel BaseModel. Quindi in altre classi che ereditano da BaseModel, è possibile impostare table il costruttore di default a tutto ciò che si desidera.

    static {
        table = "user";
    }
    • Quindi io non posso chiamare User.exists() come un metodo statico.
    • questo potrebbe essere un’indicazione che si sta abusando del static parola chiave. Mi consiglia di dare un’occhiata al tuo progetto e la rielaborazione di sbarazzarsi della necessità di una static metodo exists()
    • Cosa c’è di sbagliato con il mio progetto? Sarà più chiaro se ti ho fatto un esempio del mio utente modello, per verificare se l’id utente è valido?
    • Dicendo che non c’è qualcosa di sbagliato con il vostro disegno, solo che c’è potrebbe essere qualcosa che si deve guardare se si esegue in qualcosa come questo, dove il design del linguaggio Java non permette di fare quello che hai intenzione di fare
    • si potrebbe se hai fatto l’Utente di default del costruttore e statiche. Non ho incluso nel mio esempio (vergogna su di me) perché ho pensato vuoi vedere che è l’unico modo che avrebbe funzionato con il tuo attuale implementazione.
    • Se ho fatto quella statica.. poi potrei anche creare un’istanza più nuovo Utente gli oggetti con le loro proprietà? O sarò in grado di avere un solo User oggetto alla volta?
    • Se hai fatto un costruttore statico, allora si dovrebbe essere in grado di interagire con altri metodi statici nella classe base. Nulla ti impedisce di creare istanze di altri oggetti Utente o di avere altri costruttori che non sono statiche, con altre proprietà.

Lascia un commento