当前位置: 动力学知识库 > 问答 > 编程问答 >

java - forcing invocation of base class method

问题描述:

How does one force to invoke A's foo() method when working with instance of B (from main, and not through super call) ?

I could swear I've seen it done before. Perhaps it was C++ ??

public class Test {

static class A {

public void foo() {

System.out.println("A");

}

}

static class B extends A{

public void foo() {

System.out.println("B");

}

}

public static void main(String[] args) {

A a = new A();

B b = new B();

A aa = new B();

a.foo();

b.foo();

((A)aa).foo(); // want to print A here!

}

}

网友答案:

I could swear I've seen it done before. Perhaps it was C++?

The keyword here is virtual. This is possible in languages like C++ and C# because it's up to the programmer to define the method as virtual. I've adapted this code to C++:

#include <iostream>
using namespace std;

class A {
    public:
        void foo() {
            std::cout << "A" << endl;
        }
};
class B: public A {
    public:
        void foo() {
            std::cout << "B" << endl;
        }
};

int main() {
    // your code goes here
    A* a = new A();
    B* b = new B();
    A* aa = new B();
    a->foo();
    b->foo();
    aa->foo();
    return 0;
}

Prints:

A
B
A

Now, using the virtual keyword (just posting the relevant code from above example):

class A {
    public:
        virtual void foo() {
            std::cout << "A" << endl;
        }
};

Prints:

A
B
B

In Java you cannot expect this because all methods are virtual by default. So, to your question:

How does one force to invoke A#foo when working with instance of B and not through super call?

In Java, you can't.

网友答案:

You can't call the super method in other objects - that would violate encapsulation. The whole point is that the object controls what its overridden methods do. For instance, you might override a collection's add method to throw an exception in certain circumstances, so it could ensure only "valid" items got added to the collection. That would be pointless if callers could just bypass it with a cast!

The only reason an object gets to call super.foo() for itself is to enable one call to be implemented by using the parent implementation. It's up to the code in the class to make sure it only ever does that sensibly. Again, to take the add-in-a-collection example, if the collection overrides add it would have to have some way of adding the validated item to the collection, which it would do with super.add().

网友答案:

From outside the class definitions of A and B, you cannot force the superclass method to run. B has overridden it, so if an A reference refers to a B, B's foo method will run and print "B". No changes outside of these classes can change this polymorphic behavior -- having an actual B object will print "B".

To force it to print "B", you must change code in the A/B classes. You can mark foo as final in A so that B can't override it. Optionally, you can optionally include another method call in A's foo that B can override, so that A can guarantee that "A" will be printed, but B can still do whatever it wants when foo is called.

static class A {
    public final void foo() {
        System.out.println("A");
        // Optional.
        bar();
    }

    protected void bar() {}
}

static class B extends A {
    // Can't override "foo" now -- can't prevent "A" from being printed.
    //public void foo() {
    //    System.out.println("B");
    //}

    // Optional.
    @Override
    protected void bar() {
        System.out.println("B");
    }
}

Here, foo will always print "A", but B can also print "B" if it really wants.

分享给朋友:
您可能感兴趣的文章:
随机阅读: