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

Java 是否可以创建一个';超级';变量,然后将其更改为子类类型,并能够访问子类方法,java,inheritance,subclass,superclass,Java,Inheritance,Subclass,Superclass,我想要的是能够用超类创建一个变量,然后稍后将其“转换”为子类&能够访问子类方法。它总是被定义为一个子类,我只是不知道在定义时是哪个子类 class SuperClass { //superclass methods } class SubClass1 extends SuperClass { void subClass1method() { //do something } } class SubClass2 extends SuperClass { void sub

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

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
    }
  }
}
我不是问它为什么会这样做,而是问解决问题的正确方法&得到我想要的结果

我已经找过副本,但可能很容易漏掉一个,所以请告诉我。

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

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

当您无法控制源代码时,除了强制转换(或可能使用适配器)之外,您无法做太多事情。如果你的课程中的
instanceof
和casting听起来很熟悉,那么这可能就是你的教授所期望的

以下是您的一些选择:

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

当您无法控制源代码时,除了强制转换(或者可能使用适配器)之外,您也无法做太多的事情。如果你的课程中的
instanceof
和casting听起来很熟悉,那么这可能就是你的教授所期望的

以下是您的一些选择:

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

执行
超类a
时,您会告诉编译器您打算将
超类
类型的对象存储在变量
a
中。这意味着您也可以存储
超类
的子类,但编译器仅将
a
视为
超类
类型的对象,而不管您是否存储子类型

在运行时,没有对此进行检查,如果您设法编写代码从
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)
  }
}

执行
超类a
时,您会告诉编译器您打算将
超类
类型的对象存储在变量
a
中。这意味着您也可以存储
超类
的子类,但编译器仅将
a
视为
超类
类型的对象,而不管您是否存储子类型

在运行时,没有对此进行检查,如果您设法编写代码从
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)
  }
}

如果将变量定义为
超类a
,则只能在
a
上调用该
超类
的方法,而且无法绕过它。您只能通过强制转换创建(临时)新变量,并通过以下方式访问方法:
((子类1)a)
但是如果不先将类型从
超类
更改为
子类1
,您将永远无法直接在
上调用
子类1Method()
。可以将超类映射到子类,但是您必须自己实现映射。通常的方法是在
子类中创建一个构造函数来从旧对象创建一个新对象:
公共子类(超类c)…
。但正如OGS所说,不可能简单地将一个超类转换为一个子类,你必须手动完成。有一种设计模式说,“我有大量不同的子类,我想对它们调用各种不同的方法,但很难知道是哪种方法。”解决方案基本上是“把所有的方法都塞进一个子类,让对象来解决它。”C.f.有没有一种方法可以在不访问子类代码的情况下实现它,如:
subclass1b=newsubclass1()
a=b;
谢谢。如果将变量定义为
超类a
,则只能在
a
上调用该
超类的方法