简体   繁体   中英

Runtime polymorphism

Suppose I have class A

public class A
{
    public void method()
    {
        //do stuff
    }
}

Also another class B

public class B extends A
{
    public void method()
    {
        //do other stuff
    }
}

Now I have the following statements:

A a = new B();
a.method();

Is this an example of run time polymorphism? If yes, then is no binding is done for the reference a at compile time?

The compiler will tell you that this can't work, because there's no relationship between A and B that will allow you to write A a = new B();

B either has to extend A or both have to implement a common interface with void method() in it.

You could have answered this very quickly by trying it with the compiler. Be an experimentalist - it's faster than forums.

UPDATE:

It works, now that B extends A. The binding that you care about, dynamic binding, is done at runtime. The static compile time type for the variable "a" is class A; at runtime it is dynamically bound to a reference of type B. Yes, I would consider this to be an example of polymorphism.

I was waiting to put my answer to another post, into a more correctly classified problem. Your question fits the concept, I've tried to explain in detail. but, since I don't know how link answers, I'll just copy/paste the complete script here .... Kindly go through it, you'll understand everything that there is to understand about your problem, you've asked


let's say compiler has to resolve a call like this : *

A a = new AA(); // Assume AA to be some subclass of class A
a->someFunc(); // and we're invoking a method "someFunc()' on a

*.

Now, compiler will go over following steps methodically.

1.) Firstly, compiler knows the declared type of variable a, so it will check whether the declared type of object a ( lets call this, class A for time being ), have a method with the name someFunc() and that it must be public. This method could either be declared in class A , or it could be a derived method from one of the base class(es) of class A, but it doesn't matter to compiler and it just checks for it's existence with it's access specifier being public .

  • Needless to say any error in this step will invite a compiler error.

2.) Secondly, once the method is validated to be a part of the class A, compiler has to resolve the call to the correct method, since many methods could be there with same name (thanks to function overloading). This process of resolving correct method is called overloading resolution . Compiler achieves this by matching the signatures of the called method with all the overloaded methods that are part of the class. So, of all the someFunc() s only the correct someFunc() (matching the signatures with called method) will be found and considered further.

3.) Now comes the difficult part, It may very well happen that someFunc() may have been overridden in one of the subclasses of the class A ( lets call this class AA and needless to say it is some subclass of A ), and that variable a (declared to be of type A) may actually be referring to an object of class AA, (this is permissible in C++ to enable polymorphism). Now, if the someFunc() method is declared to be of type virtual , in base class (ie Class A) and someFunc() has been overriden by subclass(es) of A (either in AA or classes between A and AA), the correct version of someFunc() have to be found out by the compiler.

  • Now, imagine you're the compiler and you have this task of finding whether the class AA has this method. Obviously, class AA will have this method since, it is a subclass of A and public access of A in class A has already been validated in Step 1 by the compiler !!! . But Alternatively, as mentioned in previous paragraph, someFunc() may be overriden by class AA (or any other class between A and AA), which is what compiler needs to catch. Therefore, you (since, your'e playing the compiler) could do a systematic check to find the bottom-most (lowest in the inheritance tree) overridden method someFunc() starting from class A and ending at class AA. In this search, you'll look for same method signatures as was validated in overloading resolution. This method will be the method which will be invoked.

  • Now, you may be wondering, "What the heck", is this search done everytime ? ... Well, Not really. The compiler knows the overhead of finding this everytime, and as such, maintains a data-structure called Virtual Table for every class type. Think of virtual table, as mapping from method signatures (which are publicly accessible) to the function pointers. This virtual table is made by compiler during compilation process and is maintained in-memory during program execution. In our example, class A and class AA will both have their own virtual tables. And when compiler has to be find someFunc() in class AA (since actual object pointed by variable a is of type AA), it will simply find the function pointer through the virtual table of Class AA. This is as simple has hashing into the table and is a constant time operation.

Regards

AViD

The code example you've given isn't legal, so I guess the answer is that it's not a kind of polymorphism.

You can't assign a class to a variable of an unrelated type like that. I'm guessing that you might be intending for B to derive from A?

Is this an example of run time polymorphism?

As of the edit: yes that would be runtime polymorphism, since which method is actually executed depends on what is assigned to a .

Edit:

If method() would be static, then calling a.method() would always result in the version of A being called. However, you'd then just write A.method() and if you don't do that any decent IDE would warn you about that (because it might be misleading to call a static method on an instance).

End Edit.

Compile time polymorphism would be the overloading mechanism, ie the compiler decides whether to use someMethod(Number) or someMethod(Integer) depending on what it knows about the parameter that is passed (if you pass a Double or just a Number it would be the first one, if you pass an Integer it would be the second).

If yes, then is no binding is done for the reference a at compile time?

What do you mean exactly? Note that the type of a will be A so you can assign everything that extends A at runtime. The compiler will just complain if the assigned value is not an A (you might trick the compiler with a cast, but this is just evil and if this breaks your program, you have been warned ;) )

It should be

public class B extends A {
public void method()
{
//do other stuff
} }

If it were compiling, it would be the B::method() that would be called. (only if you changed your code to make the B class inherit the A class).

In this case your use your object like it was only an A, but if some methods are overidden in B, then these methods are called, instead of A's methods.

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