从父类对象调用子类方法

Posted

技术标签:

【中文标题】从父类对象调用子类方法【英文标题】:Call a child class method from a parent class object 【发布时间】:2012-07-13 01:34:17 【问题描述】:

我有以下课程

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

现在我想使用这个父类对象访问子类的方法。我还需要不时访问父类方法,所以我不能让它抽象


我想我在上面的例子中简化了太多,所以这里是实际的结构。

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 语句说“找不到 QuestionOption 的 getMultiple”。 OuestionOption 有更多的子类,它们有不同类型的方法,在子类中不常见(getMultiple 在子类中不常见)

【问题讨论】:

你有什么共同的抽象概念吗?您需要找到一种方法来表示联合概念中每个子类的细节。然后,您将能够在 Person 中定义一个方法,您可以在具有适当行为的子类中覆盖该方法。 例如,你在计算什么?为什么不在每个子类中实现calculate 方法? calculate 的 Person 参数是什么?如果这是计算的目标,也许它应该是calculate(),然后用this 做一些事情(这对于覆盖子类中的方法非常有用)。 这个问题需要更多信息 - 它不完整。请准确说明您要执行的操作以及您看到的语法错误! class是java中的保留字,Student的属性必须用别的名字 【参考方案1】:

注意:虽然这是可能的,但完全不建议这样做,因为它会破坏继承的原因。最好的方法是重构您的应用程序设计,使 NO 父子依赖关系。父母永远不需要知道自己的孩子或他们的能力。

但是.. 你应该可以这样做:

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

一种安全的方法是:

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

【讨论】:

是的!如果可以避免,不应该这样做。但是,如果您绝对无法避免从父类代码中调用子类中的方法,则可以这样做。 是什么让你觉得这里绝对不能回避? +1 以获得好的答案。如果你也指出这是一个不好的方法会更好,并且 OP 最好重新考虑他的类层次结构。 是的,绝对不是要走的路,但我只是想指出一个可能的选择..顺便说一句,已在答案中添加了警告说明.. @Keppil 几乎所有事情都是可行的,但这并不意味着通过解决他的问题我们真的在帮助他。一个糟糕的设计会产生后果,在我看来,我们应该帮助有一个干净的设计。【参考方案2】:

父类不应该知道子类。您可以实现一个方法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 Teacher
    


顺便说一句。您关于抽象类的陈述令人困惑。您可以调用定义在抽象类中的方法,但当然只能调用子类的实例。

在您的示例中,您可以将Person 抽象化,并在StudentTeacher 的实例上使用getName()

【讨论】:

在第二个示例中是 // do something with a Teacher 而不是 // do something with a Student @BugliL 是的,谢谢。已更正【参考方案3】:

这里的许多答案都建议使用“经典的面向对象分解”来实现变体类型。也就是说,任何一个变体可能需要的东西都必须在层次结构的基础上声明。我认为这是一种类型安全但通常非常糟糕的方法。您要么最终暴露所有不同变体的所有内部属性(其中大多数对于每个特定变体都是“无效的”),要么最终用大量程序方法使层次结构的 API 混乱(这意味着您必须每次都重新编译构想了一个新的程序)。

我对此犹豫不决,但这是我写的一篇博文的无耻插件,其中概述了在 Java 中实现变体类型的 8 种方法。它们都很糟糕,因为 Java 很讨厌变体类型。到目前为止,唯一正确的 JVM 语言是 Scala。

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

Scala 的创建者实际上写了一篇关于八种方式中的三种的论文。如果我能找到它,我会用一个链接更新这个答案。

更新:找到here。

【讨论】:

【参考方案4】:

为什么不直接在 Person 中编写一个空方法并在子类中覆盖它呢?并在需要时调用它:

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

这意味着您必须在两个子类中使用相同的方法,但我不明白为什么这会是个问题。

【讨论】:

【参考方案5】:

我也遇到了同样的情况,但我找到了一种解决方法,方法如下 - -

    你必须让你的方法在没有任何参数的父类中使用 - -

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

    现在,使用“cl”,您可以使用 - - 访问所有具有名称和初始化值的子类字段

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

    在这种情况下,如果您通过子类对象调用父方法,您的“this”指针将引用您的子类对象。

    您可能需要使用的另一件事是 Object obj = cl.newInstance();

如果你仍然卡在某个地方,请告诉我。

【讨论】:

【参考方案6】:
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();


   
   

【讨论】:

您好,欢迎来到 Stack Overflow。尝试添加更多 cmets(不在代码中),这将解释作者为什么您认为这是他/她正在寻找的答案。仅代码答案不是很好的答案。 好的。谢谢【参考方案7】:

一种可能的解决方案是

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

【讨论】:

感谢您的回复。我在某处读到 instanceof 是导致大量错误的雷区之一。如果我使用它,在编码时应该注意什么? 是的,在一个类中有很多 instanceof 通常不是一个好的 OO 实践,但它不应该导致任何错误,除非你有重复的类/接口名称或者你通过不同的类加载它装载机..

以上是关于从父类对象调用子类方法的主要内容,如果未能解决你的问题,请参考以下文章

从父类方法调用子类方法

为啥java的子类中必须调用父类的构造方法

学习大数据:Java基础篇之继承

学习大数据:Java基础篇之继承

如何在java中调用另一个类中子类里的一个变量?

java 子类强转父类 父类强转子类