Вызовите метод дочернего класса из родительского объекта класса

У меня есть следующие классы

class Person {
    private String name;
    void getName(){...}}

class Student extends Person{
    String class;
    void getClass(){...}
}

class Teacher extends Person{
    String experience;
    void getExperience(){...}
}

Это просто упрощенная версия моей реальной схемы. Первоначально я не знаю тип человека, который должен быть создан, поэтому функция, которая обрабатывает создание этих объектов, принимает общиеPerson объект как параметр.

void calculate(Person p){...}

Теперь я хочу получить доступ к методам дочерних классов, используя этот объект родительского класса. Мне также нужно время от времени получать доступ к методам родительского класса, такI CANNOT MAKE IT ABSTRACT.

Я предполагаю, что я слишком упростил в приведенном выше примере, так что здесь, это фактическая структура.

class Question {
  // private attributes
  :
  private QuestionOption option;
  // getters and setters for private attributes
  :
  public QuestionOption getOption(){...}
 }

 class QuestionOption{
 ....
 }
 class ChoiceQuestionOption extends QuestionOption{
 private boolean allowMultiple;
 public boolean getMultiple(){...}
 }

 class Survey{
  void renderSurvey(Question q) {
      /*
          Depending on the type of question (choice, dropdwn or other, I have to render
          the question on the UI. The class that calls this doesnt have compile time 
          knowledge of the type of question that is going to be rendered. Each question 
          type has its own rendering function. If this is for choice , I need to access 
          its functions using q. 
      */
      if(q.getOption().getMultiple())
        {...}
  }
 }

В операторе if говорится, что «не удается найти getMultiple для QuestionOption». OuestionOption имеет гораздо больше дочерних классов, которые имеют различные типы методов, которые не распространены среди детей (getMultiple не распространена среди детей)

 Marko Topolnik13 июл. 2012 г., 10:07
Например, что вы рассчитываете? Почему вы не реализуетеcalculate метод в каждом подклассе?
 Thilo13 июл. 2012 г., 10:09
И что это за параметр Person дляcalculate? Если это цель расчета, возможно, это должно бытьcalculate() а затем сделать что-то сthis вместо этого (который будет отлично работать с переопределением методов в подклассах).
 davidfrancis13 июл. 2012 г., 10:16
Этот вопрос требует дополнительной информации - он неполный. Пожалуйста, покажите, что именно вы пытаетесь сделать, и какие синтаксические ошибки вы видите!
 raven198113 июл. 2012 г., 10:16
класс является зарезервированным словом в Java, вы должны использовать другое имя для атрибута ученика
 Marko Topolnik13 июл. 2012 г., 10:06
Есть ли у вас какие-либо общие абстракции в виду? Вам необходимо найти способ представления специфики каждого подкласса в общей концепции. Тогда вы сможете определить метод вPerson что вы переопределяете в подклассах с соответствующим поведением.

Ответы на вопрос(7)

class Car extends Vehicle {
        protected int numberOfSeats = 1;

        public int getNumberOfSeats() {
            return this.numberOfSeats;

        }

        public void  printNumberOfSeats() {
          //  return this.numberOfSeats;
            System.out.println(numberOfSeats);
        }


    } 

//Parent class

  class Vehicle {
        protected String licensePlate = null;

        public void setLicensePlate(String license) {
            this.licensePlate = license;
            System.out.println(licensePlate);
        }


   public static void main(String []args) {
       Vehicle c = new Vehicle();

      c.setLicensePlate("LASKF12341"); 

//Used downcasting to call the child method from the parent class. 
//Downcasting = It’s the casting from a superclass to a subclass.

      Vehicle d = new Car();
      ((Car) d).printNumberOfSeats();


   }
   }
 16 окт. 2018 г., 09:42
Хорошо. Спасибо
 04 окт. 2018 г., 12:55
Здравствуйте, добро пожаловать в переполнение стека. Попробуйте добавить больше комментариев (не в коде), которые объяснят автору, почему вы думаете, что это ответ, который он / она ищет. Ответ только по коду не очень хороший ответ.

class Survey{
  void renderSurvey(Question q) {
  /*
      Depending on the type of question (choice, dropdwn or other, I have to render
      the question on the UI. The class that calls this doesnt have compile time 
      knowledge of the type of question that is going to be rendered. Each question 
      type has its own rendering function. If this is for choice , I need to access 
      its functions using q. 
  */
  if(q.getOption() instanceof ChoiceQuestionOption)
  {
    ChoiceQuestionOption choiceQuestion = (ChoiceQuestionOption)q.getOption();
    boolean result = choiceQuestion.getMultiple();
    //do something with result......
  }
 }
}
 17 июл. 2012 г., 08:31
Да, как правило, это не очень хорошая практика, чтобы иметь многоinstanceof в классе, но это не должно приводить к ошибкам до тех пор, пока у вас не появятся повторяющиеся имена классов / интерфейсов или вы не загрузите их через разные загрузчики классов.
 user134966316 июл. 2012 г., 17:19
Спасибо за ваш ответ. Я где-то читал, что instanceof был одним из тех минных полей, которые приводят к множеству ошибок. О чем мне следует заботиться при написании кода, если я использую это?
Решение Вопроса

NOTE: Хотя это возможно, это вообще не рекомендуется, поскольку это как бы уничтожает причину наследования. Лучшим способом было бы реструктурировать дизайн вашего приложения так, чтобыNO зависимости от родителя к ребенку. Родителю никогда не нужно знать своих детей или их способности.

Однако .. вы должны быть в состоянии сделать это так:

void calculate(Person p) {
    ((Student)p).method();
}

безопасный способ будет:

void calculate(Person p) {
    if(p instanceof Student) ((Student)p).method();
}
 13 июл. 2012 г., 10:13
Да, определенно не путь, но я только пытался указать на возможный вариант ... Кстати, добавили предупреждение к ответу ..
 13 июл. 2012 г., 10:08
Да! И это не должно быть сделано, если этого можно избежать. Но вы можете сделать это, если абсолютно не можете избежать вызова метода из дочернего класса из кода родительского класса.
 13 июл. 2012 г., 10:19
@ Keppil почти все выполнимо, но это не значит, что, решая его проблему, мы действительно помогаем ему. Плохой дизайн имеет последствия, на мой взгляд, мы должны помочь получить чистый дизайн.
 13 июл. 2012 г., 10:10
Что заставляет вас думать, что этого совершенно невозможно избежать?
 13 июл. 2012 г., 10:10
+1 за хороший ответ. Хотя было бы лучше, если бы вы также указали, что это плохой путь, и ОП было бы лучше переосмыслить его иерархию классов.

Многие из ответов здесь предлагают реализовать варианты типов с использованием «Классической объектно-ориентированной декомпозиции». То есть все, что может потребоваться в одном из вариантов, должно быть объявлено на основе иерархии. Я утверждаю, что это типобезопасный, но часто очень плохой подход. Вы либо в конечном итоге выставляете все внутренние свойства всех различных вариантов (большинство из которых являются «недопустимыми» для каждого конкретного варианта), либо заканчиваете тем, что загромождаете API иерархии множеством процедурных методов (что означает, что вам придется перекомпилировать каждый раз придумана новая процедура).

Я не решаюсь делать это, но вот постыдный плагин для написанного мной поста, в котором описывается около 8 способов сделать вариантные типы в Java. Все они отстой, потому что Java отстой в вариантах типов. Пока что единственный язык JVM, который понимает это правильно, это Scala.

http://jazzjuice.blogspot.com/2010/10/6-things-i-hate-about-java-or-scala-is.html

Создатели Scala на самом деле написали статью о трех из восьми способов. Если я смогу его отследить, я обновлю этот ответ ссылкой.

UPDATE: нашел этоВот.

Родительский класс не должен иметь знаний о дочерних классах. Вы можете реализовать методcalculate() и переопределить его в каждом подклассе:

class Person {
    String name;
    void getName(){...}
    void calculate();
}

а потом

class Student extends Person{
    String class;
    void getClass(){...}

    @Override
    void calculate() {
        // do something with a Student
    }
}

а также

class Teacher extends Person{
    String experience;
    void getExperience(){...}

    @Override
    void calculate() {
        // do something with a Student
    }

}

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

В вашем примере вы можете сделатьPerson аннотация и использованиеgetName() на примереStudent а такжеTeacher.

Почему бы вам просто не написать пустой метод в Person и переопределить его в дочерних классах? И назовите это, когда это должно быть:

void caluculate(Person p){
  p.dotheCalculate();
}

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

У меня была такая же ситуация, и я нашел способ немного поработать следующим образом - -

You have to have your method in parent class without any parameter and use - -

Class<? extends Person> cl = this.getClass(); // inside parent class

Now, with 'cl' you can access all child class fields with their name and initialized values by using - -

cl.getDeclaredFields(); cl.getField("myfield"); // and many more

In this situation your 'this' pointer will reference your child class object if you are calling parent method through your child class object.

Another thing you might need to use is Object obj = cl.newInstance();

Дайте мне знать, если вы все еще где-то застряли.

Ваш ответ на вопрос