你能用超类对象访问子类变量吗?

6
在下面的代码中,我向方法“testmethod()”传递了A类的子类B的实例化对象。
不幸的是,该方法的签名接受的是超类A而不是子类B,并且我无法更改该签名,因为它被许多类引用。
有没有一种方法(不更改testmethod()的签名),可以从testmethod()中访问被传递给testmethod的对象中的var2变量?
    public class test5  {

        public static void main(String args[]){
            B b = new B();
            testmethod(b);
        }

        public static void testmethod(A a2 ) {
            System.out.println("in testmeth->" + a2.getVar1() );   // WORKS
            System.out.println("in testmeth->" + a2.getVar2() );   // DOESNT WORK
        }
    }

    class A  {
        int var1 = 2;

        public int getVar1() {
            return var1;
        }
    }

    class B extends A {
        int var2 = 8;

        public int getVar2() {
            return var2;
        }

4
你真的不应该需要这样做。如果testmethod()请求一个A的实例,那么它应该使用A上的操作。如果它需要一个B,则方法签名应该要求一个B - David
或者你可以重载这个方法... - user1675642
4个回答

3
您可以像这样进行类型转换:
if(a2 instanceof B)
  System.out.println("in testmeth->" + ((B) a2).getVar2() );
else
  System.out.println("in testmeth->" + a2.getVar1() );

1
在所讨论的代码示例中,实例添加没有任何价值,因为它已经明确是 B 类型。 - tgkprog
2
没错,但是OP提到它被许多类使用,因此可能在传递A的实例时使用过。@tgkprog - CMPS
完美地工作,不需要更改任何方法签名! - Sarta
1
@user3302169 很高兴能够帮到你。至于那个-1...讨厌的人总是会讨厌 :) - CMPS

3
你可以进行向下转型(downcast),但这通常不是一个好的实践方法。
因此,应该这样做:
System.out.println("in testmeth->" + ((B) a2).getVar2() );

注意:如果 a2 不是类 B 的实例,则此行会导致 ClassCastException

4
值得一提的是 ClassCastException 异常和 instanceof 关键字,它们似乎一开始很神奇,但最终都会以悲剧收场。 - Boris the Spider
对我来说完美地工作了...与使用instanceof条件一起,避免异常。 - Sarta
1
一般来说,使用 instanceof 表示代码质量不佳。尽可能避免使用它。 - Boris the Spider

2
您可以重载该方法,然后在调用时将选择最具体的方法。例如:

public class test5  {

    public static void main(String args[]){
        A a = new A();
        B b = new B();
        testmethod(a);
        testmethod(b);
    }

    public static void testmethod(A a2 ) {
        System.out.println("in testmeth_a->" + a2.getVar1() );
    }

    public static void testmethod(B b2 ) {
        System.out.println("in testmeth_b->" + b2.getVar2() );
    }
}

注意:调用的方法取决于声明的类型而不是传入对象的类型。请参见此处


0

从这个最小化的例子中很难判断,但看起来你可能想把A变成一个抽象类,这需要B(和其他任何子类)实现getVar2()。当你这样做时,getVar2可以通过任何A的实例访问:

abstract class A {
   int var1 = 2;

    public int getVar1() {
        return var1;
    }
    public abstract int getVar2();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接