簡體   English   中英

從父類對象調用子類方法

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

我有以下課程

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 在子類中不常見)

注意:雖然這是可能的,但根本不推薦這樣做,因為它會破壞繼承的原因。 最好的方法是重構您的應用程序設計,以便沒有父子依賴關系。 父母不應該永遠需要知道它的孩子或他們的能力。

但是..你應該可以這樣做:

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

一個安全的方法是:

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

父類不應該了解子類。 您可以實現一個方法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抽象,並在StudentTeacher實例上使用getName()

這里的許多答案都建議使用“經典面向對象分解”來實現變體類型。 也就是說,必須在層次結構的基礎上聲明變體之一可能需要的任何內容。 我認為這是一種類型安全但通常非常糟糕的方法。 您要么最終暴露所有不同變體的所有內部屬性(其中大多數對於每個特定變體都是“無效的”),要么最終用大量程序方法弄亂層次結構的 API(這意味着您每次都必須重新編譯一個新的程序被夢想出來)。

我猶豫要不要這樣做,但這是我寫的博客文章的一個無恥插件,該文章概述了在 Java 中執行變體類型的 8 種方法。 它們都很糟糕,因為 Java 對變體類型很糟糕。 到目前為止,唯一正確的 JVM 語言是 Scala。

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

Scala 的創造者實際上寫了一篇關於八種方式中的三種的論文。 如果我能找到它,我會用鏈接更新這個答案。

更新:在這里找到它。

為什么不直接在 Person 中編寫一個空方法並在子類中覆蓋它? 並在需要時調用它:

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

這意味着你必須在兩個子類中使用相同的方法,但我不明白為什么這會是一個問題。

我遇到了同樣的情況,我通過一些工程找到了一種解決方法,如下所示 -

  1. 您必須在沒有任何參數的父類中使用您的方法並使用 - -

     Class<? extends Person> cl = this.getClass(); // inside parent class
  2. 現在,使用 'cl',您可以使用名稱和初始化值訪問所有子類字段 - -

     cl.getDeclaredFields(); cl.getField("myfield"); // and many more
  3. 在這種情況下,如果您通過子類對象調用父方法,則“this”指針將引用您的子類對象。

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

如果您仍然卡在某個地方,請告訴我。

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


   }
   }

一種可能的解決方案是

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