Использование & ldquo; перезаписанное & rdquo; переменные в подклассе с методом супер [duplicate]

Представьте, что у вас есть продукт под названием «Zebra», который может быть дополнен плагинами. Он находит плагины, ища библиотеки DLL в некоторых каталогах. Он загружает все эти DLL и использует отражение для поиска любых классов, которые реализуют IZebraPlugin, а затем вызывает методы этого интерфейса для связи с плагинами.

Это делает его полностью независимым от какого-либо конкретного класса плагина - ему все равно, что представляют собой классы. Он заботится только о том, чтобы они соответствовали спецификации интерфейса.

Интерфейсы - это способ определения точек расширяемости, подобных этому. Код, который говорит с интерфейсом, более слабо связан - на самом деле он не связан вообще с каким-либо другим конкретным кодом. Он может взаимодействовать с плагинами, написанными годами позже людьми, которые никогда не встречались с оригинальным разработчиком.

Вместо этого вы можете использовать базовый класс с виртуальными функциями - все плагины будут получены из базового класса. Но это гораздо более ограничивает, потому что класс может иметь только один базовый класс, тогда как он может реализовать любое количество интерфейсов.

9
задан Toni Joe 29 August 2015 в 19:37
поделиться

8 ответов

Когда вы расширяете класс, методы переопределяются, но поля скрыты. Динамическая диспетчеризация работает для методов, но не для полей. Почему язык разработан так, бог знает почему.

7
ответ дан user 21 August 2018 в 05:22
поделиться
  • 1
    Мы это знаем, но мы не боги. – user 29 August 2015 в 17:44
  • 2
    Правило заключается в том, что вы можете поддержать хороший ответ и плохой результат. К сожалению, у меня нет времени, чтобы дать ответ, однако только один ответ, который был занижен, верен. многие ответные ответы не отвечают на вопрос правильно. Не стесняйтесь их всех спускать, я все еще жду, но этот ответ принят. Я не знаю, почему это сделал OP, но AFAIK - хороший ответ, не всегда признанный, даже не очень одобренный. – user 29 August 2015 в 17:54
  • 3
    Вы ничего не указали, ИМХО, он даже не закрывает правильный ответ. Либо вы торопились, либо вообще не знаете языка. В любом случае у вас было время его разработать, так что уже поздно. – user 29 August 2015 в 17:59
  • 4

Dog.name - скрывает Animal.name, и это очень плохой шаблон для этого. Любая хорошая IDE предупредит вас о том, что вы это делаете.

Оба поля экземпляра существуют, и вы можете получить доступ к ним из Dog как this.name и super.name.

3
ответ дан Andreas 21 August 2018 в 05:22
поделиться
  • 1
    Что IDE будет предупреждать? – user 29 August 2015 в 18:16
  • 2
    @nikpon Я использую Eclipse , и я знаю, что это так. Я предполагаю, что NetBeans также будет. --- В Eclipse предупреждение называется . Объявление поля скрывает другое поле или переменную – Andreas 29 August 2015 в 18:18
  • 3
    Это всего лишь предупреждение, чтобы улучшить код, но это не шаблон, ИМХО, это неплохо, если язык позволяет это. В противном случае это был бы плохой язык. – user 29 August 2015 в 19:14
  • 4
    @nikpon Это так wrong . Просто потому, что вы можете что-то сделать, не делает это нормально. Возьмите любой исходный файл, измените все имена полей и переменных на случайные имена из 30 символов, затем удалите все комментарии и новые строки из источника, так что весь файл будет одной строкой. Это совершенно корректно, будет компилироваться и запускаться без проблем, но все еще настолько ошибочно . – Andreas 29 August 2015 в 19:53

Переменные не являются полиморфными в Java; они не переопределяют друг друга.

Изменить: для дальнейшей поддержки ответа Solver я помню, что мой учитель ООП утверждал, что когда вы создаете объект из Child class с reference of Parent class, переменные в Child class, которые не существуют в Parent class, по-прежнему выделяются памятью во время выполнения, но не могут быть доступны, поскольку в Parent class, которые могли получить доступ к переменной Child class.

2
ответ дан burglarhobbit 21 August 2018 в 05:22
поделиться
  • 1
    – Vince Emigh 29 August 2015 в 17:36
  • 2
    Ничего себе, это было глубоко! Сегодня узнал что-то новое. Ред. – burglarhobbit 29 August 2015 в 17:53
  • 3
    Как это объясняет, почему не полиморфные переменные ведут себя как полиморфные. – user 29 August 2015 в 18:23

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

Но если вы хотите переопределить атрибут из дочернего класса, вы можете сделать это с помощью механизма конструктора

Пример кода

class Animal{
    String name;

    public Animal(){
        name = "Animal";
    }
    public Animal(String name){
        this.name = name;
    }
    public void print(){
        System.out.println("I am an: "+name);
    }
}
class Dog extends Animal{

    Dog(){
        super("Dog");
    }

    public void print(){
        System.out.println("I am a: "+name);
    }
}

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

Результаты:

Animal object name: Animal
Dog1 object name: Dog
Dog2 object name: Dog
I am an: Animal
I am a: Dog
I am a: Dog
2
ответ дан fronthem 21 August 2018 в 05:22
поделиться

В Java мы используем метод set и get для доступа к полю. В вашем примере у нас есть класс Dog, расширяющий класс Animal.

Но если вы объявите его как Animal, если вы вызываете непосредственно поле Amimal dog1 = new Dog();, вы создаете экземпляр Dog, но объявляетесь как Animal, поэтому, когда вы вызываете dog1.name, он дает вам значение Animal.

0
ответ дан Makoto 21 August 2018 в 05:22
поделиться
  • 1
  • 2
    Это правильно, но как насчет полиморфизма? Говоря о том, что полиморфизм не применяется к переменным экземпляра, то где он применяется? – user 29 August 2015 в 17:45
  • 3
    Каждый язык программирования имеет свою реализацию Полиморфизма! Поэтому, когда вы пробовали решение, вам нужно быть в соответствии с хорошими практиками / спецификациями, предоставляемыми языком не? Может быть, мне нужно больше времени, чтобы объяснить, я пытался помочь, так что ... я улучшу это спасибо – fabien t 25 September 2015 в 23:02
  • 4
    @Makoto благодарит за все исправления. – fabien t 25 September 2015 в 23:07
1
ответ дан Saud 21 August 2018 в 05:22
поделиться

Поле Animal скрыто полем Dog, вы все равно можете получить доступ к полю Animal, указав его так же, как и вы.

Поведение, которое вы ожидаете, может быть достигнуто следующим образом:

public class Main{

    public static void main(String args[]){
        Animal animal = new Animal();
        Animal dog1 = new Dog();
        Dog dog2 = new Dog();

        System.out.println("Animal object name: " + animal.name);
        System.out.println("Dog1 object name: "+dog1.name);
        System.out.println("Dog2 object name: " + dog2.name);

        animal.print();
        dog1.print();
        dog2.print();
    }

}
class Animal {
    String name = "Animal";

    public void print(){
        System.out.println("I am an: "+name);
    }
}
class Dog extends Animal{
    public Dog() {
       this.name = "Dog"
    }
}
3
ответ дан Torge 21 August 2018 в 05:22
поделиться
  • 1
    Как добавить конструктор по умолчанию что-нибудь изменить? – user 29 August 2015 в 18:20
  • 2
    Хм, ты прав. Я смутил его, когда в Animal определен нестандартный конструктор. stackoverflow.com/questions/7187799/… Я удалил его и обновление снова, чтобы не загромождать ответ. – Torge 30 August 2015 в 13:02

Нет, это не так. Переменные экземпляра - это свойства определенного класса и не подвержены непосредственно супер или подклассам и полиморфизму.

Вы можете получить доступ к в обоих полях, используя «super.name» и «this.name» в Dog, но если вы используете только «имя», то в Dog будет принимать участие. Если вы хотите другой, вам явно нужно вызвать супер. Обратите внимание, что я говорю о доступе к переменным в классе Dog .

6
ответ дан Zarwan 21 August 2018 в 05:22
поделиться
  • 1
    @Codebender, если имя является переменной экземпляра как у собаки, так и для животных, и вы называете имя в классе Dog. Я верю, что вы вернете имя собаки. – Zarwan 29 August 2015 в 16:52
  • 2
    @Codebender Я имел в виду называть имя внутри класса Dog, а не на его экземпляре. Я отредактировал это разъяснение. – Zarwan 29 August 2015 в 16:56
  • 3
    @CodeBender верен, поля получают из ссылочного класса Animal (Not Dog) при использовании obj.name. – RamanSB 29 August 2015 в 16:58
  • 4
    @RamanSB Я согласен, что он прав, но я говорил о вызове имени из класса Dog. Я отредактировал это разъяснение. – Zarwan 29 August 2015 в 16:59
  • 5
    @Zar Строгая терминология ООП определяет атрибуты класса независимо от реализации языковой ссылки. Эта терминология взята из эпохи Smalltalk, когда программируется ООП. – user 29 August 2015 в 18:57
Другие вопросы по тегам:

Похожие вопросы: