微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

是否可以创建一个“超级”变量,然后将其更改为子类类型并能够访问子类方法

如何解决是否可以创建一个“超级”变量,然后将其更改为子类类型并能够访问子类方法

我想要的是能够使用超类创建一个变量,然后稍后将其“转换”为子类并能够访问子类方法。它总是会被定义为一个子类,我只是在定义时不知道是哪个。

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 和演员表在您的课程中听起来很熟悉,那么这可能就是您的教授所期望的。

以下是您的一些选择:

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

以下是我在控制源时实现此目标的建议..

您可以使用组合为一个类提供不同的行为,而不是为不同行为创建一个新类。请注意,如果您了解函数式接口和方法引用,这将特别方便。

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

很简单。 如果您定义类“SuperClass”的“a”,则您只能访问“SuperClass”方法! 最终,您可以将抽象方法“subClass1method”和“subClass2method”添加到“SuperClass”并在子类中实现它们。

,

当您执行 SuperClass a 时,您告诉编译器您打算将 SuperClass 类型的对象存储在变量 a 中。这意味着您也可以存储 SuperClass 的子类,但编译器只将 a 视为 SuperClass 类型的对象,无论您是否存储子类型。

在运行时没有对此进行检查,如果您设法编写从 a 上的子类调用方法的代码,它们将被调用。如果 a 不属于那个特定的子类并且没有实现被调用的方法,则会抛出异常。

但是如何强制编译器接受 a 是子类类型?铸件。您将 a 强制转换为子类,然后您可以从 a 上的子类访问方法。如果甚至无法将对象强制转换为子类,则会在编译时收到错误。

将您的 Main 类更改为以下内容,它应该可以满足您的需求:

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。