简体   繁体   English

从父类对象调用子类方法

[英]Call a child class method from a parent class object

I have the following classes我有以下课程

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

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

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

This is just a simplified version of my actual schema.这只是我实际模式的简化版本。 Initially I don't know the type of person that needs to be created, so the function that handles the creation of these objects takes the general Person object as a parameter.一开始我不知道需要创建的人的类型,所以处理这些对象的创建的函数以一般的Person对象作为参数。

void calculate(Person p){...}

Now I want to access the methods of the child classes using this parent class object.现在我想使用这个父类对象访问子类的方法。 I also need to access parent class methods from time to time so I CANNOT MAKE IT ABSTRACT .我还需要不时访问父类方法,所以我不能让它抽象


I guess I simplified too much in the above example, so here goes , this is the actual structure.我想我在上面的例子中简化了太多,所以这里是,这是实际的结构。

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())
        {...}
  }
 }

The if statement says "cannot find getMultiple for QuestionOption." if 语句表示“无法为 QuestionOption 找到 getMultiple”。 OuestionOption has many more child classes that have different types of methods that are not common among the children (getMultiple is not common among the children) OuestionOption 有更多的子类,这些子类具有不同类型的方法,这些方法在子类中不常见(getMultiple 在子类中不常见)

NOTE: Though this is possible, it is not at all recommended as it kind of destroys the reason for inheritance.注意:虽然这是可能的,但根本不推荐这样做,因为它会破坏继承的原因。 The best way would be to restructure your application design so that there are NO parent to child dependencies.最好的方法是重构您的应用程序设计,以便没有父子依赖关系。 A parent should not ever need to know its children or their capabilities.父母不应该永远需要知道它的孩子或他们的能力。

However.. you should be able to do it like:但是..你应该可以这样做:

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

a safe way would be:一个安全的方法是:

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

A parent class should not have knowledge of child classes.父类不应该了解子类。 You can implement a method calculate() and override it in every subclass:您可以实现一个方法calculate()并在每个子类中覆盖它:

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

and then进而

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

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

and

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

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

}

By the way.顺便一提。 Your statement about abstract classes is confusing.您关于抽象类的陈述令人困惑。 You can call methods defined in an abstract class, but of course only of instances of subclasses.您可以调用在抽象类中定义的方法,但当然只能调用子类的实例。

In your example you can make Person abstract and the use getName() on instanced of Student and Teacher .在您的示例中,您可以使Person抽象,并在StudentTeacher实例上使用getName()

Many of the answers here are suggesting implementing variant types using "Classical Object-Oriented Decomposition".这里的许多答案都建议使用“经典面向对象分解”来实现变体类型。 That is, anything which might be needed on one of the variants has to be declared at the base of the hierarchy.也就是说,必须在层次结构的基础上声明变体之一可能需要的任何内容。 I submit that this is a type-safe, but often very bad, approach.我认为这是一种类型安全但通常非常糟糕的方法。 You either end up exposing all internal properties of all the different variants (most of which are "invalid" for each particular variant) or you end up cluttering the API of the hierarchy with tons of procedural methods (which means you have to recompile every time a new procedure is dreamed up).您要么最终暴露所有不同变体的所有内部属性(其中大多数对于每个特定变体都是“无效的”),要么最终用大量程序方法弄乱层次结构的 API(这意味着您每次都必须重新编译一个新的程序被梦想出来)。

I hesitate to do this, but here is a shameless plug for a blog post I wrote that outlines about 8 ways to do variant types in Java.我犹豫要不要这样做,但这是我写的博客文章的一个无耻插件,该文章概述了在 Java 中执行变体类型的 8 种方法。 They all suck, because Java sucks at variant types.它们都很糟糕,因为 Java 对变体类型很糟糕。 So far the only JVM language that gets it right is Scala.到目前为止,唯一正确的 JVM 语言是 Scala。

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

The Scala creators actually wrote a paper about three of the eight ways. Scala 的创造者实际上写了一篇关于八种方式中的三种的论文。 If I can track it down, I'll update this answer with a link.如果我能找到它,我会用链接更新这个答案。

UPDATE : found it here .更新:在这里找到它。

Why don't you just write an empty method in Person and override it in the children classes?为什么不直接在 Person 中编写一个空方法并在子类中覆盖它? And call it, when it needs to be:并在需要时调用它:

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

This would mean you have to have the same method in both children classes, but i don't see why this would be a problem at all.这意味着你必须在两个子类中使用相同的方法,但我不明白为什么这会是一个问题。

I had the same situation and I found a way around with a bit of engineering as follows - -我遇到了同样的情况,我通过一些工程找到了一种解决方法,如下所示 -

  1. You have to have your method in parent class without any parameter and use - -您必须在没有任何参数的父类中使用您的方法并使用 - -

     Class<? extends Person> cl = this.getClass(); // inside parent class
  2. Now, with 'cl' you can access all child class fields with their name and initialized values by using - -现在,使用 'cl',您可以使用名称和初始化值访问所有子类字段 - -

     cl.getDeclaredFields(); cl.getField("myfield"); // and many more
  3. In this situation your 'this' pointer will reference your child class object if you are calling parent method through your child class object.在这种情况下,如果您通过子类对象调用父方法,则“this”指针将引用您的子类对象。

  4. Another thing you might need to use is Object obj = cl.newInstance();您可能需要使用的另一件事是 Object obj = cl.newInstance();

Let me know if still you got stucked somewhere.如果您仍然卡在某个地方,请告诉我。

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();


   }
   }

One possible solution can be一种可能的解决方案是

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......
  }
 }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM