Есть ли способ переопределить переменные класса в Java? - PullRequest
142 голосов
/ 26 марта 2009
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();
}

Функция doIt выведет «папа». Есть ли способ заставить его печатать "сын"?

Ответы [ 16 ]

2 голосов
/ 26 марта 2009

Вы не можете переопределить переменные в классе. Вы можете переопределить только методы. Вы должны держать переменные закрытыми, иначе вы можете получить много проблем.

2 голосов
/ 26 марта 2009

только путем переопределения printMe():

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

ссылка на me в методе Dad.printMe неявно указывает на статическое поле Dad.me, поэтому вы так или иначе изменяете то, что printMe делает в Son ...

0 голосов
/ 14 августа 2018

Переменные не участвуют в отбрасывании. Только методы делают. Вызов метода разрешается во время выполнения, то есть решение о вызове метода принимается во время выполнения, но переменные определяются только во время компиляции. Следовательно, вызывается эта переменная, чья ссылка используется для вызова, а не для объекта времени выполнения.

Взгляните на следующий фрагмент:

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);
  }

}

Когда вы запустите код, консоль покажет:

Inside Honda
Inside Honda
Inside bike

Max_Speed = 150
Max_Speed = 90
Max_Speed = 90
0 голосов
/ 05 мая 2018

Нет. Переменные класса (также применимые к переменным экземпляра) не обладают переопределением в Java, поскольку переменные класса вызываются на основе типа вызывающего объекта. Добавлен еще один класс (Человек) в иерархию, чтобы сделать его более понятным. Итак, теперь у нас есть

Сын расширяет Папа расширяет Человека

В приведенном ниже коде мы пытаемся перебрать массив объектов Human, Dad и Son, но во всех случаях он печатает значения человеческого класса, поскольку тип вызывающего объекта был Human.

    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
        }
    }
}

Распечатает

  • человек
  • человек
  • человек

Таким образом, нет переопределения переменных класса.

Если мы хотим получить доступ к переменной класса фактического объекта из ссылочной переменной его родительского класса, нам нужно явно сообщить об этом компилятору, приведя родительскую ссылку (объект Human) к его типу.

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

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

Напечатает

  • папа
  • сын

О том, как часть этого вопроса: - Как уже предлагалось переопределить метод printMe () в классе Son, затем при вызове

Son().printMe();

Переменная класса «папа» папы «me» будет скрыта, потому что ближайшая декларация (из метода printme () класса Son) «me» (в классе Son) получит приоритет.

0 голосов
/ 10 июня 2015

Зачем вам нужно переопределять переменные, когда вы можете легко переназначить их в подклассах.

Я следую этой схеме, чтобы обойти языковой дизайн. Предположим, что в вашей среде есть весомый класс обслуживания, который необходимо использовать в разных вариантах в нескольких производных приложениях. В этом случае лучший способ настроить логику суперкласса - переназначить его «определяющие» переменные.

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 голосов
/ 17 июля 2012

Конечно, рекомендуется использовать закрытые атрибуты, а также методы получения и установки, но я протестировал следующее, и это работает ... См. Комментарий в коде

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();
    }
}

Оооо ... я просто переопределил правила наследования или поставил Oracle в сложное положение? Для меня защищенная статическая строка String Me явно переопределена, как вы можете видеть, когда вы запускаете эту программу. Кроме того, для меня нет никакого смысла, почему атрибуты не должны быть переопределенными.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...