簡體   English   中英

是否可以創建一個“超級”變量,然后將其更改為子 class 類型並能夠訪問子類方法

[英]Is it possible to Create a 'super' variable and then change it to a sub class type and be able to access the subclass methods

我想要的是能夠使用超類創建一個變量,然后稍后將其“轉換”為子類並能夠訪問子類方法。 它總是被定義為一個子類,我只是在定義時不知道是哪個子類。

class SuperClass {
  //superclass methods
}

class SubClass1 extends SuperClass {
  void subClass1method() {
    //do something
  }
}

class SubClass2 extends SuperClass {
  void subClass2method() {
    //do something different
  }
}

class Main {
  public static void main ( String [] args ) {
    SuperClass a;

    if (*some reson to be SubClass1*) {
      a = new SubClass1();
      a.subClass1Method();     //this is undefined it says
      //a instanceof SubClass1 returns true which is what confused me
    } else {
      a = new SubClass2();
      a.subClass2Method();     //this is undefined it says
    }
  }
}

我不是在問它為什么這樣做,而是在問解決它並獲得我想要的結果的正確方法。

我一直在尋找重復的,但很容易錯過一個,所以請告訴我。

當您無法控制源時,除了強制轉換(或可能使用適配器)之外,您無能為力。 如果您的課程中instanceof和 cast 聽起來很熟悉,那么這可能就是您的教授所期望的。

以下是您的一些選擇:

// to execute those subclass specific methods without casting..
public static void main ( String [] args ) {
    SuperClass superClass;
    if (true /*some reson to be SubClass1*/) {
        SubClass1 subClass1 = new SubClass1();
        subClass1.subClass1Method();
        superClass = subClass1;
    } else {
        SubClass2 subClass2 = new SubClass2();
        subClass2.subClass2Method();
        superClass = subClass2;
    }
    // ... ...
}

// using instanceof and casting
public static void main ( String [] args ) {
    SuperClass superClass;
    if (true /*some reson to be SubClass1*/) {
        superClass = new SubClass1();
    } else {
        superClass = new SubClass2();
    }

    // ... ... ...

    if(superClass instanceof SubClass1) {
        ((SubClass1) superClass).subClass1Method();
    } else if(superClass instanceof SubClass2) {
        ((SubClass2) superClass).subClass2Method();
    }
}

以下是我的建議,以在您控制源代碼時實現此目標。

而不是針對不同行為的新 class,您可以使用組合來為一個 class 提供不同的行為。 請注意,如果您了解功能接口和方法引用,這將特別方便。

public class SuperClass {
    private MyBehavior behavior;

    public void setBehavior(MyBehavior behavior) { this.behavior = behavior; }

    public void doBehavior() { this.behavior.doBehavior(); }
}

public interface MyBehavior { public void doBehavior(); }

public class MyGoodBehavior implements MyBehavior {
    @Override public void doBehavior() { System.out.print("good behavior"); }
}

public class MyBadBehavior implements MyBehavior {
    @Override public void doBehavior() { System.out.print("bad behavior"); }
}

public static void main(String[] args) {
    SuperClass a = new SuperClass();
    a.setBehavior(new MyBadBehavior());
    
    a.doBehavior();
}

這很簡單。 如果您定義 class“SuperClass”的“a”,則只能訪問“SuperClass”方法。 最終,您可以將抽象方法“subClass1method”和“subClass2method”添加到“SuperClass”並在子類中實現它們。

當您執行SuperClass a時,您告訴編譯器您打算將SuperClass類型的對象存儲在變量a中。 這意味着您也可以存儲SuperClass的子類,但編譯器僅將a視為 SuperClass 類型的SuperClass ,無論您是否存儲子類型。

在運行時沒有對此進行檢查,如果您設法編寫從 a 上a子類調用方法的代碼,它們將被調用。 如果a不是那個特定的子 class 並且不實現被調用的方法,則會引發異常。

但是如何強制編譯器接受a是子類類型呢? 鑄件。 您將a強制轉換為子類,然后您可以從 a 上a子類訪問方法。 如果甚至無法將 object 強制轉換為子類,則在編譯時會出現錯誤。

將您的Main class 更改為以下內容,它應該可以滿足您的要求:

class Main {
  public static void main ( String [] args ) {
    SuperClass a;

    if (*some reson to be SubClass1*) {
      a = new SubClass1();
      ((SubClass1)a).subClass1Method();     // Casting 'a' as SubClass1
    } else {
      a = new SubClass2();
      ((SubClass2)a).subClass2Method();     // Casting 'a' as SubClass2
    }
  }
}

在編譯時和運行時強制轉換工作和不工作的幾個例子:

class SuperClass { }

class SubClass1 extends SuperClass { }

class SubClass2 extends SuperClass { }

class Main {
  public static void main(String... args) {
    SuperClass a;
    SubClass1 b;
    SubClass2 c;

    b = new SubClass1();
    a = b;  // autocast to SuperClass

    a = new SubClass1();
    b = a;  // Compile error
    b = (SubClass1) a;  // explicit cast

    c = new SubClass2();

    method(b);   // works
    method(c);   // compiles, but will throw exception at runtime inside method
  }

  private static void method(SuperClass object) {
    SubClass1 b = (SubClass1) object;  // allowed by compiler but will throw exception at runtime in the second call, method(c)
  }
}

暫無
暫無

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

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