简体   繁体   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

What I would like is to be able to create a variable with the superclass and then 'turn' it into the subclass later & be able to access the subClasses methods.我想要的是能够使用超类创建一个变量,然后稍后将其“转换”为子类并能够访问子类方法。 It will always be defined to a subclass I just don't know which when defining.它总是被定义为一个子类,我只是在定义时不知道是哪个子类。

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

I am not asking why it does this but the correct way to work around it & get the results I want.我不是在问它为什么这样做,而是在问解决它并获得我想要的结果的正确方法。

I have looked for duplicates but could have easily missed one so please let me know.我一直在寻找重复的,但很容易错过一个,所以请告诉我。

When you don't have control of the source then there's not too much you can do besides casting (or possibly using adapters).当您无法控制源时,除了强制转换(或可能使用适配器)之外,您无能为力。 If instanceof and casting sound familiar from your lessons then that's probably what your prof is expecting.如果您的课程中instanceof和 cast 听起来很熟悉,那么这可能就是您的教授所期望的。

Here are some of your options:以下是您的一些选择:

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

Below is my recommendation to achieve this goal when you have control of the source..以下是我的建议,以在您控制源代码时实现此目标。

Rather than a new class for different behaviors you could just use composition to provide different behaviors to the one class.而不是针对不同行为的新 class,您可以使用组合来为一个 class 提供不同的行为。 Note that this is especially convenient if you understand Functional Interfaces and Method References.请注意,如果您了解功能接口和方法引用,这将特别方便。

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

It's simple.这很简单。 If you define "a" of class "SuperClass" you can only access "SuperClass" methods.如果您定义 class“SuperClass”的“a”,则只能访问“SuperClass”方法。 Eventually you could add abstract methods "subClass1method" and "subClass2method" to "SuperClass" and implement them in the subclasses.最终,您可以将抽象方法“subClass1method”和“subClass2method”添加到“SuperClass”并在子类中实现它们。

When you do SuperClass a you tell the compiler that you intend to store objects of type SuperClass in the variable a .当您执行SuperClass a时,您告诉编译器您打算将SuperClass类型的对象存储在变量a中。 It means that you can store subclasses of SuperClass as well, but the compiler only sees a as an object of type SuperClass , regardless if you are storing a sub type.这意味着您也可以存储SuperClass的子类,但编译器仅将a视为 SuperClass 类型的SuperClass ,无论您是否存储子类型。

At runtime there's no check for this, if you manage to write code that calls methods from a subclass on a , they will be called.在运行时没有对此进行检查,如果您设法编写从 a 上a子类调用方法的代码,它们将被调用。 If a is not of that particular sub class and don't implement the called method, an exception would be thrown.如果a不是那个特定的子 class 并且不实现被调用的方法,则会引发异常。

But how do you force the compiler to accept that a is of the subclass type?但是如何强制编译器接受a是子类类型呢? Casting.铸件。 You cast a to the subclass, then you can access methods from subclass on a .您将a强制转换为子类,然后您可以从 a 上a子类访问方法。 If it´s not even possible to cast an object to a subclass, you get an error at compile time.如果甚至无法将 object 强制转换为子类,则在编译时会出现错误。

Change your Main class to the following and it should do what you want:将您的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
    }
  }
}

A few examples of when casting work and don't work at compile time and runtime:在编译时和运行时强制转换工作和不工作的几个例子:

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.

相关问题 如何更改子类中超类的变量类型? - How to change the type of a variable of a super class in a subclass? 为什么我们不能使用父类的引用变量来访问其子类的方法(方法在父类中不可用)? - why cant we use a reference variable of super class to access methods of its subclass(methods not available in super class)? 在超类方法中使用子类成员变量? - Use subclass member variable in super class methods? 当引用类型为超类时,子类无法访问超类的受保护方法 - Sub-class not able to access the protected method of super-class when the reference is of type super-class java.java中的继承如何通过超类方法更改子类的变量值 - inheritance in java.how to change the variable value of sub class by super class methods 使用super作为引用类型时,无法访问子类中的方法 - Can't access methods in sub class when using the super as the reference type 子类对象的超类引用变量访问子类的属性而不是父类的属性 - Super-class reference variable to a sub-class object accesses the subclass's attribute instead of the super's 可以在超类中声明一个返回类型为subclass的对象的方法吗? - Possible to declare a method in super class that returns an object of type subclass? 您可以通过 Java 中的超级 class 访问子 class 变量吗 - Can you access sub class variable via super class in Java 如何从通用超类访问子类变量 - How To Access Sub Class Variable From Generic Super Class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM