Java Inheritance Confusion [дубликат]

Более простой способ - просто сгенерировать SVG в строку, создать HTML-элемент оболочки и вставить строку svg в элемент HTML с помощью $("#wrapperElement").html(svgString). Это прекрасно работает в Chrome и Firefox.

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

8 ответов

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

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

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

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

3
ответ дан Andreas 16 August 2018 в 10:24
поделиться
  • 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
2
ответ дан burglarhobbit 16 August 2018 в 10:24
поделиться

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

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

Пример кода

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 16 August 2018 в 10:24
поделиться

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

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

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

Когда вы вызываете метод print на animal, JVM сначала ищет метод print в объекте dog. Если в объекте dog не было print, JVM будет искать суперкласс Dog. Поскольку он находит метод print в классе Dog, он начинает его выполнять. Поле имени в классе Dog скрывает поле имени, которое было унаследовано от класса Animal. Его так же, как:

public class Test {
static String name = "xyz";
public static void main(String[] args) {
    {
      String name = "abc";
      System.out.println(name); // abc is printed
    }
    System.out.println(name); // xyz is printed
}
}

Внутри блока есть локальная переменная name. Таким образом, глобальная переменная name скрыта. Но когда вы выходите из блока, появляется локальная переменная.

ПРИМЕЧАНИЕ:

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

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

Вы сделали плохой дизайн.

1
ответ дан Saud 16 August 2018 в 10:24
поделиться

Поле 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 16 August 2018 в 10:24
поделиться

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

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

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

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