Наследование Java - PullRequest
       6

Наследование Java

3 голосов
/ 21 октября 2010

Итак, я пытался найти правильный способ получить то, что должно быть довольно простым наследованием, чтобы функционировать (так, как я хочу;)), и я терплю неудачу.Подумайте об этом:

class Parent
{
  public String name = "Parent";

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

class Child extends Parent
{
  public String name = "Child";
  public Child()
  {
    doStuff();
  }
}

Я понимаю, что Java не делает то, что я ожидаю в этом случае, так как по некоторым причинам переменные-члены не переопределяются так же, как методы, но мой вопрос в том, чтоправильный способ достичь поведения, которое я ожидаю?Я хотел бы, чтобы мой базовый класс содержал некоторые функции, которые работают с переменными-членами, предоставленными / определенными данным подклассом.Я думаю, что get / sets может работать, но тогда это разрушает мою способность просто вызывать super () и заставлять мой базовый класс выполнять конструкцию, необходимую, чтобы мои подклассы содержали связку конструкций вместо того, чтобы изолировать их от базового класса.

Любые конструктивные предложения приветствуются.

Ответы [ 6 ]

8 голосов
/ 21 октября 2010

Вы всегда можете заменить переменную на getter, если вам нужен такой тип 'переменная наследования'. Не уверен, что «переменная-наследственность» ((c)) в целом является хорошим шаблоном проектирования.

class Parent {
    public void doStuff() {
        System.out.println(getName());
    }

    public String getName() {
        return "Parent";
    }
}

class Child extends Parent {
    public Child() {
        doStuff();
    }

    public String getName() {
        return "Child";
    }
}

Или вы можете иметь защищенный конструктор в классе Parent, взяв имя для использования.

редактировать
Я бы не назвал это «взломом». И версия с передачей параметра в родительский конструктор тоже может быть довольно элегантной.

class Parent {
    private final String name;

    // don't let use to invoke this constructor, only for child classes
    protected Parent(String name) {
        this.name = name;
    }

    // public constructor for users
    public Parent() {
        this("Parent");
    }

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

class Child extends Parent {
    public Child() {
        super("Child");
        doStuff();
    }
}

Есть ли у вас какие-либо идеи, почему Java, похоже, отказалась от концепции наследования переменных-членов?
Java отказалась от многих концепций C ++ (начиная с печально известного множественного наследования), потому что они не добавили такой большой ценности в язык, но увеличили его сложность.
Хотя я ничего не имею против наследования переменных, я не страдаю и без этой концепции. И лично мне нравится язык простой и чистый.

6 голосов
/ 21 октября 2010

Вам действительно нужны две разные name переменные для одного экземпляра? Действительно ли у вас есть идея, что у объекта есть «имя, когда просматривается как родитель» и «имя, когда просматривается как ребенок»? Если нет, просто укажите одну переменную в классе Parent.

Как класс Parent узнает, какие переменные будут предоставлены ребенком? Если каждый подкласс будет иметь одинаковый набор переменных, почему они не входят в родительский класс?

Если бы вы могли привести более конкретный пример проблемы, которую вы пытаетесь решить, было бы легче дать конкретный ответ.

3 голосов
/ 21 октября 2010

Переменная подкласса name равна shadowing Переменная суперкласса с тем же именем. Поэтому, когда Child объявляет и присваивает name, это другая отдельная переменная.

Вместо этого рассматривайте name как свойство родительского объекта, унаследованного дочерним элементом, и передайте name в качестве аргумента конструктору Parent. Затем вы вызываете super("Child") из дочернего конструктора.

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

2 голосов
/ 21 октября 2010

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

class Parent {   
    protected string name;

    public Parent() { name = "parent"};   
    public doStuff() {
        System.out.println(name);   
    }
}

class Child extends Parent {   
    public Child() {
        name = "child";
        doStuff();
    }
}
1 голос
/ 21 октября 2010

То, что вы пытаетесь сделать, не будет работать в Java. В Java атрибуты, объявленные в родительском классе, не переопределяются в дочернем классе.

Если вам нужно полиморфное поведение, вам нужно объявить атрибуты private и объявить соответствующие методы getter в родительском классе, которые вы можете переопределить в дочернем классе.

В качестве альтернативы:

class Child extends Parent {
    public Child() {
        name = "Child";
        doStuff();
    }
}

хотя ответ @ shoebox639 делает это более элегантным способом, который позволяет вам объявить атрибут как final. (Изменяемые публичные атрибуты не очень хорошая идея ...)

0 голосов
/ 05 мая 2016

Вам не нужно переопределять переменную-член в подклассе.Вы можете написать свой код так, как @Stephen C говорит

class Child extends Parent {
    public Child() {
        name = "Child";
        doStuff();
    }
}

В вашем посте

Я бы хотел, чтобы мой базовый класс содержал некоторые функции, которые работают с переменными-членами, предоставленными / определенными данным подклассом.

Сначала вы напишите свой суперкласс, и на этом этапе ваш суперкласс не знает о вашем подклассе.

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