简体   繁体   中英

Java Interface question regarding polymorphism

So I have this:

interface C {
    void shutUp();
}

class A {
    public void speak() {
       System.out.println("Class a");
    }
}

class B extends A implements C {
    public void shutUp() {
        System.out.println("Saying nothing...");
    }

    public void speak() {
        System.out.println("Class B");
    }
}

If I do this, it works:

A obj = new B();
obj.speak()

But I can't do obj.shutUp() Why not? I have a feeling that I am just confused on something very basic.

Thanks!

A's static type is not connected to C, thus you cannot do this command, it would be the same to do:

A obj = new A();
obj.shutUp();

(which is obviously illegal..)
the only one who can use both is B

B obj = new B();
obj.shutUp();
obj.speak();

this is all connected to the fact that Java is static typing

Because A is not a C - it does not implement the interface - and you can't instantiate an interface that way, because there is no default constructor.

A reference of type A doesn't have a method shutUp() , so it's no surprise that it doesn't work.

And your code uses incorrect keywords: it's class and interface for Java. Case matters.

By saying A obj = new B(); you are decouple your code from a specific implementation of the interface. So obj will not have access to shutup() function, which was implemented in class b.

您的obj具有类A接口,因为它是变量的类型。

The type of obj is defined as A ; therefore, obj can only use members that are available to A . Because C inherits from A , C has all the members required to be considered a form of A , which is why it allows you to create a new C in an A variable. Only by casting it to type C can you use all of the members that belong to C .

In your question is mistake: You can't create C object because it's interface - so I think you want create B object, then:

This is because obj is A not C, to use shutUp method you can:

((C) obj).shutUp() // cast to C type
((B) obj).shutUp() // cast to B type

Or declare:

B obj = new B();
obj.shutUp();

Or:

C obj = new B(); // (!) but: you can't (without casting) call speak method
obj.shutUp();

A obj = new C();

as C is interface, u cant create instance of interface. Please correct the question.

the reason to why you can't call shutUp on obj is this:

obj is not an object, it's a pointer or reference. the object you create when you do new B() is one thing, obj (or "how you use the object") is a separate thing. you use the object with the help of a reference (in this case obj), which lets you access different sides of the actual object.

if the reference you use to access the object is of the type that references the object at hand (ie has the same name) then you can access the whole object through this reference. otherwise you can only access those parts of the object that the reference type can see.

in your example, the reference type is A, ie obj sees only the A part of whatever object it's referring to. therefore it can't access the B/C part of the object, event though the object has these behaviors.

Other people have answered this already, but do note that there is a way to call shutUp() without casting to B or C :

A obj = new B();
try {
    Method shutUp = obj.getClass().getMethod("shutUp", null);
    shutUp.invoke(obj, null);
}
catch (Exception ignored) {}
A obj = new B();

Here you are creating an instance of "B" which is of type "A". ie you are saying "I want to make an object B and name it obj which is of type A".

In class A there is only one method which is accessible. It did not implement C

public void speak() {}

To be able to access all the methods of class B, you should create an instance of "B" of type "B"

B obj2 = new B();

This way you will be able to access

 public void shutUp() {}

This is because it is B which implements class "C".

One way to be able to access both methods using "obj" is to make A implement C

Object created by new B() can be used as an object of either of three types — A, B or C. But you can't declare a variable of several types.

Since B is a subtype of A and C you can use its instance as an instance of any of those types. Eg

B o = new B();
A aO = o;
C cO = o;

Now you can use o to access both speak and shutUp methods, you can use aO to access speak method and cO to access shutUp method. It doesn't matter which variable you will use the methods called will be the same because those variables all reference the same object. Why you can't use aO to invoke shutUp in Java is because you have declared your variable with a type that doesn't have such a method. Although you know that this particular object does have that method doesn't make it so in general.

class D extends A {
    public void speak(){
        System.out.println("Class D");
    }
}

List<A> as = new ArrayList<A>();
as.add(new A());
as.add(new B());
as.add(new D());

A a0 = as.get(0);
A a1 = as.get(1);
A a2 = as.get(2);

a0.speak(); // >> Class A
a1.speak(); // >> Class B
a2.speak(); // >> Class D 

Now, in this example you have instances of three different classes in a single collection. When you pass this collection around or modify it you will never know which class is each object actually is. All you know is that they all are of type A, they are guaranteed to be of that type though actually they can be of any subtype of A (like B or D).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM