C'è un modo per sovrascrivere le variabili di classe in Java?


class Dad
{
    protected static String me = "dad";

    public void printMe()
    {
        System.out.println(me);
    }
}

class Son extends Dad
{
    protected static String me = "son";
}

public void doIt()
{
    new Son().printMe();
}

La funzione doIt stamperà "papà". C'è un modo per farlo stampare "figlio"?

Author: James P., 2009-03-26

16 answers

Sì. Ma poiché la variabile è interessata, viene sovrascritta (dando nuovo valore alla variabile. Dare una nuova definizione alla funzione è Override).Just don't declare the variable but initialize (change) in the constructor or static block.

Il valore verrà riflesso quando si utilizza nei blocchi della classe genitore

Se la variabile è statica, modificare il valore durante l'inizializzazione stessa con il blocco statico,

class Son extends Dad {
    static { 
       me = 'son'; 
    }
}

Oppure cambia nel costruttore.

È anche possibile modificare il valore in seguito in qualsiasi blocco. Si rifletterà nella super classe

 48
Author: Vivek MVK, 2016-06-30 06:41:01

In breve, no, non c'è modo di sovrascrivere una variabile di classe.

Non si sovrascrivono le variabili di classe in Java si nascondono. L'override è per esempio metodi. Nascondersi è diverso dall'override.

Nell'esempio che hai dato, dichiarando la variabile di classe con il nome 'me' in class Son nascondi la variabile di classe che avrebbe ereditato dalla sua superclasse Dad con lo stesso nome 'me'. Nascondere una variabile in questo modo non influisce sul valore della variabile di classe "io" nella superclasse Papà.

Per la seconda parte della tua domanda, su come farlo stampare "figlio", imposterei il valore tramite il costruttore. Sebbene il codice sottostante si discosti molto dalla tua domanda originale, lo scriverei in questo modo;

public class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public void printName() {
        System.out.println(name);
    }
}

Il JLS fornisce molti più dettagli sul nascondersi nella sezione 8.3-Dichiarazioni di campo

 91
Author: Mike, 2013-04-19 19:24:50

Sì, basta ignorare il metodo printMe():

class Son extends Dad {
        public static final String me = "son";

        @Override
        public void printMe() {
                System.out.println(me);
        }
}
 31
Author: romaintaz, 2014-05-12 06:35:03

È possibile creare un getter e quindi sovrascrivere tale getter. È particolarmente utile se la variabile che stai sovrascrivendo è una sottoclasse di se stessa. Immagina che la tua super classe abbia un membro Object ma nella tua sottoclasse questo è ora più definito per essere un Integer.

class Dad
{
        private static final String me = "dad";

        protected String getMe() {
            return me;
        }

        public void printMe()
        {
                System.out.println(getMe());
        }
}

class Son extends Dad
{
        private static final String me = "son";

        @Override
        protected String getMe() {
            return me;
        }
}

public void doIt()
{
        new Son().printMe(); //Prints "son"
}
 15
Author: John Strickler, 2011-12-27 18:25:03

Se hai intenzione di sovrascriverlo, non vedo un motivo valido per mantenere questa statica. Suggerirei l'uso dell'astrazione (vedi codice di esempio). :

     public interface Person {
        public abstract String getName();
       //this will be different for each person, so no need to make it concrete
        public abstract void setName(String name);
    }

Ora possiamo aggiungere il papà:

public class Dad implements Person {

    private String name;

    public Dad(String name) {
        setName(name);
    }

    @Override
    public final String getName() {
    return name;
    }

    @Override
    public final void setName(String name) {
        this.name = name;
    }
}

Il figlio:

public class Son implements Person {

    private String name;

    public Son(String name) {
        setName(name);
    }

    @Override
    public final String getName() {
        return name;
    }

    @Override
    public final void setName(String name) {
        this.name = name;
    }
}

E papà ha incontrato una bella signora:

public class StepMom implements Person {

    private String name;

    public StepMom(String name) {
        setName(name);
    }

    @Override
    public final String getName() {
        return name;
    }

    @Override
    public final void setName(String name) {
        this.name = name;
    }
}

Sembra che abbiamo una famiglia, diciamo al mondo i loro nomi:

public class ConsoleGUI {

    public static void main(String[] args) {
        List<Person> family = new ArrayList<Person>();
        family.add(new Son("Tommy"));
        family.add(new StepMom("Nancy"));
        family.add(new Dad("Dad"));
        for (Person person : family) {
            //using the getName vs printName lets the caller, in this case the
            //ConsoleGUI determine versus being forced to output through the console. 
            System.out.print(person.getName() + " ");
            System.err.print(person.getName() + " ");
            JOptionPane.showMessageDialog(null, person.getName());
    }
}

}

Sistema.fuori Uscita: Tommy Nancy Papà
Sistema.err è lo stesso di cui sopra (ha solo carattere rosso)
JOption Uscita:
Tommy allora
Nancy allora
Papà

 10
Author: nckbrz, 2016-05-02 13:27:28

Sembra un difetto di progettazione.

Rimuovere la parola chiave static e impostare la variabile ad esempio nel costruttore. In questo modo Son imposta la variabile su un valore diverso nel suo costruttore.

 6
Author: Patrick Cornelissen, 2009-03-26 11:17:14

Sebbene sia vero che le variabili di classe possono essere nascoste solo nelle sottoclassi e non sovrascritte, è comunque possibile fare ciò che si desidera senza sovrascrivere printMe () nelle sottoclassi e reflection è tuo amico. Nel codice seguente ometto la gestione delle eccezioni per chiarezza. Si noti che dichiarare me come protected non sembra avere molto senso in questo contesto, poiché verrà nascosto nelle sottoclassi...

class Dad
  {
    static String me = "dad";

    public void printMe ()
      {
        java.lang.reflect.Field field = this.getClass ().getDeclaredField ("me");
        System.out.println (field.get (null));
      }
  }
 4
Author: Sergey Ushakov, 2013-07-21 16:28:24
class Dad
{
    protected static String me = "dad";

    public void printMe()
    {
        System.out.println(me);
    }
}

class Son extends Dad
{
    protected static String _me = me = "son";
}

public void doIt()
{
    new Son().printMe();
}

... stamperà "figlio".

 3
Author: user2895864, 2013-10-18 17:53:51

Solo sostituendo printMe():

class Son extends Dad 
{
    public void printMe() 
    {
        System.out.println("son");
    }
}

Il riferimento a me nel metodo Dad.printMe punta implicitamente al campo statico Dad.me, quindi in un modo o nell'altro stai cambiando ciò che printMe fa in Son...

 2
Author: Dan Vinton, 2009-03-26 11:10:49

Non è possibile sovrascrivere le variabili in una classe. È possibile ignorare solo i metodi. Dovresti mantenere le variabili private altrimenti potresti avere molti problemi.

 2
Author: Ionel Bratianu, 2009-03-26 11:19:56

Stampa infatti 'dad', poiché il campo non è sovrascritto ma nascosto. Ci sono tre approcci per farlo stampare'figlio':

Approccio 1: sovrascrivi PrintMe

class Dad
{
    protected static String me = "dad";

    public void printMe()
    {
        System.out.println(me);
    }
}

class Son extends Dad
{
    protected static String me = "son";

    @override
    public void printMe()
    {
        System.out.println(me);
    }
}

public void doIt()
{
    new Son().printMe();
}

Approccio 2: non nascondere il campo e inizializzarlo nel costruttore

class Dad
{
    protected static String me = "dad";

    public void printMe()
    {
        System.out.println(me);
    }
}

class Son extends Dad
{
    public Son()
    {
        me = "son";
    }
}

public void doIt()
{
    new Son().printMe();
}

Approccio 3: utilizzare il valore statico per inizializzare un campo nel costruttore

class Dad
{
    private static String meInit = "Dad";

    protected String me;

    public Dad() 
    {
       me = meInit;
    }

    public void printMe()
    {
        System.out.println(me);
    }
}

class Son extends Dad
{
    private static String meInit = "son";

    public Son()
    {
        me = meInit;
    }

}

public void doIt()
{
    new Son().printMe();
}
 2
Author: Rik Schaaf, 2015-04-17 03:16:39

Https://docs.oracle.com/javase/tutorial/java/IandI/hidevariables.html

Si chiama Nascondere i campi

Dal link qui sopra

All'interno di una classe, un campo che ha lo stesso nome di un campo nella superclasse nasconde il campo della superclasse, anche se i loro tipi sono diversi. All'interno della sottoclasse, il campo nella superclasse non può essere referenziato dal suo nome semplice. Invece, il campo deve essere accessibile tramite super, che è coperto nel prossimo sezione. In generale, non è consigliabile nascondere i campi in quanto rende il codice difficile da leggere.

 2
Author: sadjkas sadal, 2017-04-24 04:19:07

Ovviamente usare attributi privati, e getter e setter sarebbe la cosa consigliata da fare, ma ho testato quanto segue e funziona... Vedere il commento nel codice

class Dad
{
    protected static String me = "dad";

    public void printMe()
    {
        System.out.println(me);
    }
}

class Son extends Dad
{
    protected static String me = "son";

    /* 
    Adding Method printMe() to this class, outputs son 
    even though Attribute me from class Dad can apparently not be overridden
    */

    public void printMe()
    {
        System.out.println(me);
    }
}

class Tester
{
    public static void main(String[] arg)
    {
        new Son().printMe();
    }
}

Sooo ... ho appena ridefinito le regole dell'eredità o ho messo Oracle in una situazione complicata ? Per me, protected static String me è chiaramente sovrascritto, come puoi vedere quando esegui questo programma. Inoltre, non ha alcun senso per me perché gli attributi non dovrebbero essere sovrascrivibili.

 0
Author: Pixel, 2012-07-17 12:46:06

Perché si desidera sovrascrivere le variabili quando è possibile riassegnarle facilmente nelle sottoclassi.

Seguo questo schema per aggirare il design del linguaggio. Si supponga un caso in cui si dispone di una classe di servizio pesante nel framework che deve essere utilizzata in diversi gusti in più derivati applications.In in questo caso, il modo migliore per configurare la logica della super classe è riassegnare le sue variabili "definitive".

public interface ExtensibleService{
void init();
}

public class WeightyLogicService implements ExtensibleService{
    private String directoryPath="c:\hello";

    public void doLogic(){
         //never forget to call init() before invocation or build safeguards
         init();
       //some logic goes here
   }

   public void init(){}    

}

public class WeightyLogicService_myAdaptation extends WeightyLogicService {
   @Override
   public void init(){
    directoryPath="c:\my_hello";
   }

}
 0
Author: premganz, 2015-06-11 10:11:04

N. Le variabili di classe (applicabili anche alle variabili di istanza) non presentano funzionalità di sovrascrittura in Java poiché le variabili di classe vengono invocate in base al tipo di oggetto chiamante. Aggiunta un'altra classe (umana) nella gerarchia per renderla più chiara. Quindi ora abbiamo

Figlio estende Papà estende umana

Nel codice seguente, proviamo a iterare su una matrice di oggetti Umani, Papà e Figlio, ma stampa i valori della Classe Umana in tutti i casi come il tipo di oggetto chiamante era Umano.

    class Human
{
    static String me = "human";

    public void printMe()
    {
        System.out.println(me);
    }
}
class Dad extends Human
{
    static String me = "dad";

}

class Son extends Dad
{
    static String me = "son";
}


public class ClassVariables {
    public static void main(String[] abc)   {
        Human[] humans = new Human[3];
        humans[0] = new Human();
        humans[1] = new Dad();
        humans[2] = new Son();
        for(Human human: humans)   {
            System.out.println(human.me);        // prints human for all objects
        }
    }
}

Stamperà

  • umano
  • umano
  • umano

Quindi nessuna sovrascrittura delle variabili di classe.

Se vogliamo accedere alla variabile di classe dell'oggetto reale da una variabile di riferimento della sua classe genitore, dobbiamo dirlo esplicitamente al compilatore lanciando il riferimento genitore (oggetto umano) al suo tipo.

    System.out.println(((Dad)humans[1]).me);        // prints dad

    System.out.println(((Son)humans[2]).me);        // prints son

Stamperà

  • papà
  • figlio

Su come parte di questo domanda: - Come già suggerito sovrascrivi il metodo PrintMe () nella classe Son, quindi alla chiamata

Son().printMe();

La variabile di classe di papà "me" sarà nascosta perché la dichiarazione più vicina(dal metodo Son class printme ()) del "me"(nella classe Son) otterrà la precedenza.

 0
Author: Developer, 2018-05-05 16:21:18

Le variabili non prendono parte all'overrinding. Solo i metodi lo fanno. Una chiamata al metodo viene risolta in fase di runtime, ovvero la decisione di chiamare un metodo viene presa in fase di runtime, ma le variabili vengono decise solo in fase di compilazione. Quindi viene chiamata quella variabile il cui riferimento viene utilizzato per chiamare e non dell'oggetto runtime.

Dai un'occhiata al seguente frammento:

package com.demo;

class Bike {
  int max_speed = 90;
  public void disp_speed() {
    System.out.println("Inside bike");
 }
}

public class Honda_bikes extends Bike {
  int max_speed = 150;
  public void disp_speed() {
    System.out.println("Inside Honda");
}

public static void main(String[] args) {
    Honda_bikes obj1 = new Honda_bikes();
    Bike obj2 = new Honda_bikes();
    Bike obj3 = new Bike();

    obj1.disp_speed();
    obj2.disp_speed();
    obj3.disp_speed();

    System.out.println("Max_Speed = " + obj1.max_speed);
    System.out.println("Max_Speed = " + obj2.max_speed);
    System.out.println("Max_Speed = " + obj3.max_speed);
  }

}

Quando si esegue il codice, la console mostrerà:

Inside Honda
Inside Honda
Inside bike

Max_Speed = 150
Max_Speed = 90
Max_Speed = 90
 0
Author: Ananta S E, 2018-09-11 16:58:13