簡體   English   中英

Java Inheritance:如何從父 class 覆蓋實例變量/字段?

[英]Java Inheritance: How to override instance variables/fields from parent class?

更新:我可以將變量從私有、static 或最終更改。

我有一個父母 class 和一個孩子 class。 我想在class 中重用一個方法。 通常,這就像super.methodFromParentClass()一樣簡單,你就完成了。 但是,當我這樣做時,我想重用的方法使用來自父 class 的實例變量數據,這是錯誤的,或者更確切地說,我想要這種行為。 我在子class中有不同的初始化數據,需要傳遞到我想要重用的方法中。 如果您查看我想重用的方法(下面只是一個簡單的示例,但想法是相同的),我將在其中創建多個對象,這些對象使用 class 的實例變量。所以你可以看到為什么當我調用super.methodIWantToReuse時它不起作用,因為它會獲取父數據並將其傳遞給對象,即使我真的希望它傳遞我在子 class 中初始化的數據。 我的真實示例還創建了更多的對象,並且我有更多的實例變量,所以如果可能的話,我真的想重用這段代碼(DRY 原則)。

我怎樣才能解決這個問題? 將使用gettergetFirstName()並在子 class 中覆蓋它們,因此當我調用super.methodIWantToReuse()時使用運行時多態性,將獲取/使用子 class 實例變量數據是唯一的方法???

public class ParentClass {
   private static final String firstName = "Billy Ray";
   private static final String lastName = "Cyrus";
   private static final int age = 58;
   private static final String city = "Hunstville";

public boolean methodIWantToReuse() {
   Object1 obj1 = new Object(firstName, lastName);
   
   Object2 obj2 = new Object(age,city);

   Object3 obj3 = new Object(obj1, obj2);

   Object4 obj4 = new Object(obj3);

   // Passing in the objects created above as argument, which have the Parent instance variable data
   return someRandomMethodHere(obj4);
}
public class ChildClass {
    private static final String firstName = "Miley";
    private static final String lastName = "Cyrus";
    private static final int age = 27;
    private static final String city = "Los Angeles";

public boolean methodIWantToReuse() {
   // DOESN'T WORK CORRECTLY, because ends up using the instance variable data of PARENT class, but it 
   // needs to use CHILD class instance variable data

   super.methodIWantToReuse();
}

您不能覆蓋 class 的字段。 只有方法可以被覆蓋。 在您的情況下,您必須使用 getter 並在子 class 中覆蓋它們。

您的父 class 實例變量是私有的,因此您不能從子 class 更新它們。 因此,您可以使用參數化方法或為實例變量(或受保護的變量本身)創建受保護的 setter/getter。 在您的情況下,變量是最終的,因此您實際上甚至無法更新它們。 所以從技術上講,不可能在父 class 中使用子 class 變量。

如果您將變量更新為protected並刪除static/final修飾符(正如您在評論中提到的那樣)。 從父 class 調用方法之前,在調用 super 方法之前更新變量數據。 你可以這樣做:

方法 1:在調用父 class 方法之前更新父 class 中的數據。

父 Class:

public class ParentClass {

    protected String firstName = "Billy Ray";
    protected String lastName = "Cyrus";
    protected int age = 58;
    protected String city = "Hunstville";

    public boolean methodIWantToReuse() {
        // Passing in the objects created above as argument, which have the Parent
        // instance variable data
         Object1 obj1 = new Object(firstName, lastName);

         Object2 obj2 = new Object(age,city);

         Object3 obj3 = new Object(obj1, obj2);

         Object4 obj4 = new Object(obj3);
        return someRandomMethodHere(obj4);;
    }
}

兒童 Class:

public class ChildClass extends ParentClass {
    protected String firstName = "Miley";
    protected String lastName = "Cyrus";
    protected int age = 27;
    protected String city = "Los Angeles";

    public boolean methodIWantToReuse() {
        // Update data in Parent class first

        super.firstName = firstName;
        super.lastName = lastName;
        super.age = age;
        super.city = city;
        return super.methodIWantToReuse();
    }
}

方法2:如果你想使用參數化方法使其無狀態,你可以這樣做:

父 Class:

public class ParentClass {

    protected String firstName = "Billy Ray";
    protected String lastName = "Cyrus";
    protected int age = 58;
    protected String city = "Hunstville";

    public boolean methodIWantToReuse() {
        
        return methodIWantToReuse(this.firstName, this.lastName, this.age, this.city);
    }

    public boolean methodIWantToReuse(String firstName, String lastName, int age, String city) {
        // Passing in the objects created above as argument, which have the Parent
        // instance variable data
         Object1 obj1 = new Object(firstName, lastName);

         Object2 obj2 = new Object(age,city);

         Object3 obj3 = new Object(obj1, obj2);

         Object4 obj4 = new Object(obj3);
        return someRandomMethodHere(obj4);;
    }
}

兒童 Class:

public class ChildClass extends ParentClass {
    protected String firstName = "Miley";
    protected String lastName = "Cyrus";
    protected int age = 27;
    protected String city = "Los Angeles";

    public boolean methodIWantToReuse() {
        // Update data in Parent class first
        return super.methodIWantToReuse(this.firstName, this.lastName, this.age, this.city);
    }
}

注意:保持局部變量名稱與 class 級別變量相同不是一個好習慣。 但為了便於理解,將其保留在這里。

如果您真的是指instance variables而不是您的static variables (或class variables ),如示例中所示,您可以通過更改訪問修飾符並刪除final關鍵字來使您的子類可以訪問它們。

If, however, you actually mean static variables , you cannot reassign them in each subclass as they would all share the same static variables defined by the ParentClass , meaning the last loaded class would be the only result you get by calling your ParentClass#methodIWantToReuse .

最好的辦法是使用 OOP 通過使用所需的 arguments 實例化新的單個對象並使用它們來發揮您的優勢。

我的意思是,而不是這樣做:

public class Example {
  public static class ParentClass {
    protected String name;
    protected int age;
    
    public ParentClass() {
      name = "The parent";
      age = 35;
    }
    
    public String methodIWantToReuse() {
      return name + " is " + age + " years old.";
    }
  }
  
  public static class AChildClass extends ParentClass {
    public AChildClass() {
      name = "Alice";
      age = 13;
    }
  }
  
  public static class AnotherChildClass extends ParentClass {
    public AnotherChildClass() {
      name = "Bob";
      age = 21;
    }
  }
  
  public static void main(String[] args) {
    // Prints "The parent is 35 years old."
    System.out.println(new ParentClass().methodIWantToReuse());
    // Prints "Alice is 13 years old."
    System.out.println(new AChildClass().methodIWantToReuse());
    // Prints "Bob is 21 years old."
    System.out.println(new AnotherChildClass().methodIWantToReuse());
  }
}

做這個:

public class Example {
  public static class ParentClass {
    protected String name;
    protected int age;
    
    // Variables instantiated here to not cause confusion
    public ParentClass() {
      name = "The parent";
      age = 35;
    }
    
    public String methodIWantToReuse() {
      return name + " is " + age + " years old.";
    }
  }
  
  public static class ChildClass extends ParentClass {
    public ChildClass(String name, int age) {
      this.name = name;
      this.age = age;
    }
  }
  
  public static void main(String[] args) {
    // Prints "The parent is 35 years old."
    System.out.println(new ParentClass().methodIWantToReuse());
    // Prints "Alice is 13 years old."
    System.out.println(new ChildClass("Alice", 13).methodIWantToReuse());
    // Prints "Bob is 21 years old."
    System.out.println(new ChildClass("Bob", 21).methodIWantToReuse());
  }
}

這也應該遵循 DRY 原則,因為您希望盡可能高效地重用您的代碼,而不是在技術上一遍又一遍地編寫相同的代碼。

如您所見,我無需重寫ParentClass#methodIWantToReuse或調用ChildClass的超級實現。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM