Java-геттеры возвращают null

Я работаю над абстрактным упражнением суперкласса для класса, и я застрял в том, почему мои геттеры возвращают ноль. Согласно тому, как продемонстрировал мой инструктор, сеттеры переопределяются в подклассах, а геттеры должны быть окончательными методами в суперклассе. Геттеры работают, когда я перемещаю их в подкласс, поэтому я предполагаю, что это как-то связано с тем, что они находятся в отдельных классах, но, поскольку я новичок в объектно-ориентированном программировании, я понятия не имею, почему это так и/или как это исправить.

Абстрактный суперкласс:

public abstract class ProgrammingCourse {

    private double credits;
    private  String courseName;

    public final double getCredits() {
        return credits;
    }

    public abstract void setCredits(double credits);

    public final String getCourseName() {
        return courseName;
    }

    public abstract void setCourseName(String courseName);

Пример подкласса:

  public class AdvancedJavaCourse extends ProgrammingCourse {

    private double credits;
    private String courseName;

    @Override
    public void setCourseName(String courseName) {
        if (courseName == null || courseName.length() == 0) {
            JOptionPane.showMessageDialog(null,
                    "Error: courseName cannot be null or empty");
            System.exit(0);
        }
        this.courseName = courseName;
    }

    @Override
    public void setCredits(double credits) {
        this.credits = credits;
    }

Как я пытаюсь работать с этим в моем основном:

     ProgrammingCourse[] courses = {new AdvancedJavaCourse(), 
     new IntroJavaCourse(), new IntroToProgrammingCourse()};

    courses[0].setCourseName("adv Java");
    courses[1].setCourseName("Intro Java");
    courses[2].setCourseName("Intro Programming");
    for (ProgrammingCourse pc : courses) {
        System.out.println(pc.getCourseName());
    }

    AdvancedJavaCourse advJava = new AdvancedJavaCourse();
    advJava.setCourseName("Advanced Java");

    System.out.println(advJava.getCourseName());

person TeamNormal    schedule 31.01.2016    source источник
comment
Почему вы дублируете переменные класса? Вы создаете эффект затенения.   -  person PM 77-1    schedule 31.01.2016
comment
Где конструкторы? Вы не инициируете атрибуты суперкласса (и атрибуты подкласса тоже). Попробуйте сделать это, и проблема будет решена.   -  person Jessica    schedule 31.01.2016
comment
Я тоже задавался вопросом о повторяющихся переменных, однако это точный код, который мой учитель продемонстрировал в классе, так что.....   -  person TeamNormal    schedule 31.01.2016
comment
а что касается конструкторов, то они у меня были, но значения по-прежнему нулевые, поэтому я их удалил.   -  person TeamNormal    schedule 31.01.2016


Ответы (2)


Есть несколько проблем с вашим кодом. Начиная с AdvancedJavaCourse следует удалить поля credits и courseName. Они доступны из ProgrammingCourse.

Теперь, когда у вас есть только одно объявление для каждого из этих полей, вы должны либо пометить поля как protected внутри ProgrammingCourse, либо создать несколько геттеров/сеттеров, чтобы вы могли изменить их значение с AdvancedJavaCourse.

person DominicEU    schedule 31.01.2016

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

Это то, что называется затенением переменной/поля. . Даже если это разрешено языком, этого следует избегать.

Здесь происходит то, что экземпляр AdcanceJavaCourse имеет в общей сложности 4 поля, две пары credit и courseName, те, которые объявлены ProgrammingCourse, и те, которые объявлены в самом AdvanceJavaCourse.

Код в ProgrammingCourse будет читать и записывать переменные, объявленные в этом классе, тогда как код в AdvanceJavaCourse будет обращаться к полям, объявленным в этом классе.

Вероятно, здесь вы хотите удалить объявление поля в AdvanceJavaCourse и объявить поля в ProgrammingCourse как protected.

Другая возможность — объявить эти поля как приватные в ProgramingCourse, дать простое тело сеттерам в ProgramingCourse:

  public void setField(Type value) {
     field = value;
  }

Любые специализированные переопределения в этих подклассах сеттера или геттера могут получить доступ к закрытым полям с помощью родительских геттеров сеттеров с префиксом super.:

@Override 
public void setField(Type value) {
    ...
    super.setField(processedValue);
    ...
}
person Valentin Ruano    schedule 31.01.2016