Java Forum / General / January 2008
Why is dynamic polymorphism so useful?
failure_to@yahoo.co.uk - 26 Dec 2007 01:26 GMT hello
1) With dynamic polymorphism, calls to actual methods are resolved at run time. So why is that so important? Why is that so much better than letting the compiler figure out which version of method to call ( based on the type of object being referred by reference variable )? Result would still be the same ... if superclass variable referred to child class object, then method of child class object would be called!
2) Why isn't polymorphism also enabled for resolving calls to static methods? Wouldn't there be some benefits by allowing that?
thank you
John W. Kennedy - 26 Dec 2007 03:17 GMT > 1) With dynamic polymorphism, calls to actual methods are resolved at > run time. So why is that so important? Why is that so much better [quoted text clipped - 3 lines] > child class object, then method of child class object would be > called!
> 2) Why isn't polymorphism also enabled for resolving calls to static > methods? Wouldn't there be some benefits by allowing that? These questions are, in the most literal meaning of the word, nonsense. Try starting over with a better textbook, because the one you're learning from isn't working. Honestly, I'm not trying to blow you off, but your misunderstanding of the situation is so severe that I'd have to write ten or twenty pages to create an answer for you -- and I'm not a teacher.
 Signature John W. Kennedy "The bright critics assembled in this volume will doubtless show, in their sophisticated and ingenious new ways, that, just as /Pooh/ is suffused with humanism, our humanism itself, at this late date, has become full of /Pooh./" -- Frederick Crews. "Postmodern Pooh", Preface
Lew - 26 Dec 2007 04:14 GMT > hello > [quoted text clipped - 5 lines] > child class object, then method of child class object would be > called! Actually, not, because at compile time the actual type of the object isn't known.
Look at it this way, there are two things in a program that have types: the variable and the object. Variables have compile-time type, objects have run-time type. Variables have scope, objects have lifetimes. A variable can go out of scope and disappear, but the object to which it pointed will live on.
Classic example:
List <String> messages = new ArrayList <String> ();
The variable 'messages' has only the compile-time type List <String>. Thus it only can invoke methods known to the interface.
The actual object has a run-time type of ArrayList. This can change during the program's lifetime:
later: messages = new TreeList <String> ();
Now the run-time of the object has changed, perhaps in response to some condition that doesn't always happen.
The compile-time type remains List. No way the compiler can know ahead of time that at certain times the dispatch for add() will have to follow a different logic path. That happens through the object, not the variable, at run time, not compile time.
> 2) Why isn't polymorphism also enabled for resolving calls to static > methods? Wouldn't there be some benefits by allowing that? I don't remember them off the top of my head, perhaps it was from the Java Language Specification (JLS) itself, but there are explanations you can quickly google up.
My take on it is that you need an object to dispatch through, because it depends on run-time type. There is no object, nor run-time type to a class - a class is a class. All right, there is a kind of "object", but it's not at all the same kind as the Java language means by an "object".
The class thing carries a bunch of information that pertain to that class. There's nothing to dispatch through - no change in a class's state that says, "OK, now we dispatch a method" - because there is no object of a subtype to say, "Use my stuff." There's just the class, itself.
So you call a static method Foo.doGlobalThing() - based on what would you say, "dispatch to a subtype"? Nothing, that's what. You have to call the doGlobalThing() in the Foo class - you can't know what subtype might be intended. The notion of an override has no referent, therefore no meaning.
 Signature Lew
Roedy Green - 26 Dec 2007 07:03 GMT >1) With dynamic polymorphism, calls to actual methods are resolved at >run time. So why is that so important? Why is that so much better [quoted text clipped - 3 lines] >child class object, then method of child class object would be >called! You can get a more accurate match. If a reference is an Object but the object itself is a Rabbit, you can get the specialised Rabbit method. Java does not know to use the specialised Rabbit method at compile time.
There is extra overhead for runtime matching. Even without it, you can in your general method look for special cases and dispatch them to more special methods. To me, the problem does not come up often enough for it to be worth the overhead.
Over time that tradeoff my change. Lots of thing we would not dream of doing before for programmer convenience become necessities with sufficient RAM and CPU power.
 Signature Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
Roedy Green - 26 Dec 2007 07:05 GMT >2) Why isn't polymorphism also enabled for resolving calls to static >methods? Wouldn't there be some benefits by allowing that? You would need a reference that could refer to several different class methods. That sounds a lot like a standard object pointer. So we are right back to ordinary instance methods.
 Signature Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
Eric Sosman - 26 Dec 2007 14:10 GMT > hello > [quoted text clipped - 5 lines] > child class object, then method of child class object would be > called! Please explain how the compiler can figure out which class' method to call in
Number n = (Math.random() < 0.5) ? new Integer(42) : new Double(42.0); String s = n.toString(); // Integer's toString, or Double's?
> 2) Why isn't polymorphism also enabled for resolving calls to static > methods? Wouldn't there be some benefits by allowing that? When calling a static method, what is the `this' object whose actual nature would determine the method to be called?
 Signature Eric Sosman esosman@ieee-dot-org.invalid
Wayne - 26 Dec 2007 19:46 GMT > Please explain how the compiler can figure out which class' > method to call in > > Number n = (Math.random() < 0.5) > ? new Integer(42) : new Double(42.0); > String s = n.toString(); // Integer's toString, or Double's? The best way to learn is to write programs and examine the results. Here I created foo.java:
class foo { public static void main (String[]args) { Number n = (Math.random() < 0.5) ? new Integer(42) : new Double(42.0); String s = n.toString(); } }
Compiled with "javac foo.java", then running "javap -s -c foo" produces:
Compiled from "foo.java" class foo extends java.lang.Object{ foo(); Signature: ()V Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return
public static void main(java.lang.String[]); Signature: ([Ljava/lang/String;)V Code: 0: invokestatic #2; //Method java/lang/Math.random:()D 3: ldc2_w #3; //double 0.5d 6: dcmpg 7: ifge 26 10: new #5; //class java/lang/Integer 13: dup 14: bipush 42 16: invokespecial #6; //Method java/lang/Integer."<init>":(I)V 19: invokevirtual #7; //Method java/lang/Integer.intValue:()I 22: i2d 23: goto 39 26: new #8; //class java/lang/Double 29: dup 30: ldc2_w #9; //double 42.0d 33: invokespecial #11; //Method java/lang/Double."<init>":(D)V 36: invokevirtual #12; //Method java/lang/Double.doubleValue:()D 39: invokestatic #13; //Method java/lang/Double.valueOf:(D)Ljava/lang/Double; 42: astore_1 43: aload_1 44: invokevirtual #14; //Method java/lang/Object.toString:()Ljava/lang/String; 47: astore_2 48: return
}
===================================================
Even if you don't understand all of the JVM instructions you should be able to follow this code: call Math.random, compare the result to 0.5, if less then create a new Integer (lines 10-23), else create a new Double (lines 26-38). The value is converted to a String in lines 39-47. It should be clear from line 39 the type of the expression you questioned is...irrelevant! Note the "i2d" instruction on line 22. The compiler is pulling the primitive int from the Integer (line 19), converting to a double (line 22). On the other hand, if a Double is created, its value is extracted to a primitive (line 36).
Then in either case a third object, a Double, is created from that double (line 39). However the compiler invokes Object.toString, not Double.toString (line 44) for reasons that elude me; perhaps an optimizing compiler would use the more specific method.
When in doubt you can check the JVM specs (2nd ed is available on-line). Playing around like this is a terrific way to learn.
> When calling a static method, what is the `this' object whose > actual nature would determine the method to be called? The keyword "this" is normally bound to the Object reference the method is invoked on. But for static methods, "this" keyword isn't set at all and can't be used.
A mental model can simplify your thinking here (even if it is incorrect). Every class is represented by an Object, created in a special way by the ClassLoader, of type java.lang.Class. You can think of any methods and fields declared as static as methods and fields of that class Object (again, that's not really correct). Thus, when you create a class Foo and some Foo objects you also have a Class object named "Foo", where the system keeps the Foo class static fields (a.k.a. "class variables") and methods, along with the ability to create objects of type Foo. So when you invoke a static method the "this" reference, if it existed, would not refer to any Foo type object but rather to the Class object named Foo. Thus such a method has access to static fields and other static methods, but this Class object named Foo doesn't contain any instance methods or fields. (This mental model is too simple to explain how it really works but it should help with understanding this one aspect of static versus instance. Please don't shoot me.)
Consider the method main: when starting the JVM, you specify a class, not a class and method. The JVM will create the Class object for the specified class but no other objects. So only a static method could be invoked at that time, which is why the main method must be static.
While some languages only have (the equivalent of) instance fields and methods, Java provides you the choice. The annoying part is that Java uses the same operator to access static and instance fields and methods leading to some confusion. No doubt keeping the number of operators low(er) made the compilers easier to write.
So if you want per-object properties use instance variables ("fields"). If you want single "global" or "shared" properties use static variables (or fields). If you want polymorphism use instance methods. If you don't and you don't need access to instance fields, use static methods.
>From your post I'm guessing you question the wisdom of providing non-polymorphic methods. You are not alone but personally I often find them useful, especially for collections of "utility" methods that don't need access to any instance fields. (Take a look at the utility classes in java.lang and java.util packages. You'll find most of the methods of these classes are declared static.)
Hope this helps!
-Wayne
Lasse Reichstein Nielsen - 26 Dec 2007 22:01 GMT > The best way to learn is to write programs and examine the results. > Here I created foo.java: [quoted text clipped - 9 lines] > Compiled with "javac foo.java", then running "javap -s -c foo" > produces: ...
> Note the "i2d" instruction on line 22. The compiler > is pulling the primitive int from the Integer (line 19), converting to a > double (line 22). On the other hand, if a Double is created, its value > is extracted to a primitive (line 36). I can see that the conditional expression caused some unexpected coercions. Try this instead:
Number n; if (Math.random() < 0.5) { n = new Integer(42): } else { n = new Double(42.0); }
or perhaps just
Number n = (Math.random() < 0.5) ? (Number) new Integer(42) : (Number) new Doubler(42.0);
> Then in either case a third object, a Double, is created from that > double (line 39). However the compiler invokes Object.toString, not > Double.toString (line 44) for reasons that elude me; perhaps an > optimizing compiler would use the more specific method. It calls Object.toString virtually, because that is the most specific toString that exists on the Number class.
It would be possible to optimize, if an analysis showed that only Double values would ever become that value of Number type variable. That analysis would have to be absolutely certain, even in the presence of multiple threads simultaneously fiddling with other object's fields using reflection. A mistake in the analysis would make it into the class file, and the JVM would have no chance of correcting it. That is why most optimizations are better left for the runtime HotSpot optimizer, since it can optimize based on what is actually happening, and can backtrack and use the unoptimized version if the optimziation enabling conditions change.
In some cases (e.g., the example using "if" above), you can't know at compile time what type of object it will be, so no compiler optimization is possible.
/L
 Signature Lasse Reichstein Nielsen - lrn@hotpop.com DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html> 'Faith without judgement merely degrades the spirit divine.'
Lew - 26 Dec 2007 23:41 GMT >> The best way to learn is to write programs and examine the results. >> Here I created foo.java: [quoted text clipped - 29 lines] > Number n = (Math.random() < 0.5) ? (Number) new Integer(42) > : (Number) new Doubler(42.0); The important point being that the compiler can have no way of knowing which result will pertain at run time. No need to read assembler for that; it's plenty clear from just the Java code.
 Signature Lew
Wayne - 27 Dec 2007 15:25 GMT >>> The best way to learn is to write programs and examine the results. >>> Here I created foo.java: [quoted text clipped - 33 lines] > which result will pertain at run time. No need to read assembler for > that; it's plenty clear from just the Java code. Hmm. Could someone post an SSCCE using standard Java classes, where the polymorphism shows in the output of javap? All my attempts at using toString result in Object.toString method being invoked.
-Wayne
Lew - 27 Dec 2007 15:44 GMT > Hmm. Could someone post an SSCCE using standard Java classes, > where the polymorphism shows in the output of javap? All my > attempts at using toString result in Object.toString method > being invoked. Perhaps something like a Collection add() where the implementation is ArrayList or LinkedList or TreeSet or HashSet, chosen at runtime?
 Signature Lew
Wayne - 27 Dec 2007 16:31 GMT > Hmm. Could someone post an SSCCE using standard Java classes, > where the polymorphism shows in the output of javap? All my > attempts at using toString result in Object.toString method > being invoked. Or perhaps even better, is there a freely available debugger (say in Netbeans or Eclipse) that can display an object's vtable (or whatever its called in Java)? And to save me hours of learning what is that debugger's command(s) to do that?
-Wayne
Tim Smith - 30 Dec 2007 07:24 GMT > > I can see that the conditional expression caused some unexpected coercions. > > Try this instead: [quoted text clipped - 14 lines] > result will pertain at run time. No need to read assembler for that; it's > plenty clear from just the Java code. It depends on how sneaky the compiler wants to be. If it notices that this code is only called once, couldn't it generate the random number at compile time, and then just compile the appropriate branch?
 Signature --Tim Smith
Patricia Shanahan - 30 Dec 2007 14:38 GMT >>> I can see that the conditional expression caused some unexpected coercions. >>> Try this instead: [quoted text clipped - 18 lines] > this code is only called once, couldn't it generate the random number at > compile time, and then just compile the appropriate branch? No, because the result of Math.random() depends on the time of the first call, and the number of prior calls to it anywhere in the program, including in code that is not available at compile time. I assume Math.random() was used in the example to represent any method whose result depends on run time data, and varies from call to call.
In any case, the compiler needs a strategy that will work for multiple calls.
Patricia
Lew - 30 Dec 2007 16:09 GMT Tim Smith wrote:
>> It depends on how sneaky the compiler wants to be. If it notices that >> this code is only called once, couldn't it generate the random number >> at compile time, and then just compile the appropriate branch?
> No, because the result of Math.random() depends on the time of the first > call, and the number of prior calls to it anywhere in the program, [quoted text clipped - 4 lines] > In any case, the compiler needs a strategy that will work for multiple > calls. Even conceptually the idea of pre-compiling a random result is repugnant. What would that do to cryptography?
In fact, random() is supposed to depend on unknowable, future extrinsic events, like the output of your system's entropy generator. We should understand its role as close to being truly random. The "pseudo" in "pseudorandom" isn't supposed to mean, "deterministic, decided before we even deploy the program". It's like the old math joke - any time I need a random number I pick 17.
 Signature Lew
Arne Vajhøj - 30 Dec 2007 17:03 GMT > Tim Smith wrote: >>> It depends on how sneaky the compiler wants to be. If it notices [quoted text clipped - 19 lines] > even deploy the program". It's like the old math joke - any time I need > a random number I pick 17. You are not supposed to use Math.random or java.util.Random.* in cryptography - java.security.SecureRandom exist to handle those cases.
Arne
Tim Smith - 30 Dec 2007 20:14 GMT > In fact, random() is supposed to depend on unknowable, future extrinsic > events, like the output of your system's entropy generator. We should > understand its role as close to being truly random. The "pseudo" in > "pseudorandom" isn't supposed to mean, "deterministic, decided before we even > deploy the program". It's like the old math joke - any time I need a random > number I pick 17. You've confused java.util.Random with java.util.SecureRandom. The former, which is what Math.random() uses, is a linear congruential generator. It is deterministic and completely predicatable from the current state. No external events affect it.
(And if you don't know the current state, observing consecutive output of the generator allows the state to be recovered. That's why such generators are completely unsuitable for cryptographic work. They were broken a very long time ago--I believe it is even mentioned in the first edition of Knuth volume 3, to give an idea of how long ago they were broken).
Linear contruential generators are OK where you care about are the statistical properties of the output, and do not care about the predictability of it.
 Signature --Tim Smith
Lew - 30 Dec 2007 20:22 GMT >> In fact, random() is supposed to depend on unknowable, future extrinsic >> events, like the output of your system's entropy generator. We should [quoted text clipped - 18 lines] > statistical properties of the output, and do not care about the > predictability of it. Yes, well, now two people have corrected my statement here. What I was driving for and missed was that even regular random() or Random should have those statistical properties. Just returning "17" probably won't.
 Signature Lew
Lew - 30 Dec 2007 20:29 GMT Tim Smith wrote:
>> You've confused java.util.Random with java.util.SecureRandom. The >> former, which is what Math.random() uses, is a linear congruential >> generator. It is deterministic and completely predicatable from the >> current state. No external events affect it. As Patricia Shanahan's post pointed out, there is some dependence on something, in the choice of seed for the no-arg constructor. It's not the same every time and one might not know the seed.
For the purposes of this thread, also as Patricia pointed out, the fact that the seed is (likely) different each time obviates a compiler's ability to predict it, or to turn it into a constant. It might be cryptographically hackable, but not in service of a compiler optimization.
 Signature Lew
Lasse Reichstein Nielsen - 30 Dec 2007 16:16 GMT > It depends on how sneaky the compiler wants to be. If it notices that > this code is only called once, couldn't it generate the random number at > compile time, and then just compile the appropriate branch? It cannot tell that it is only called once. Apart from the undecidability of the general problem, the compiler doesn't know how many times the program will be run.
Also, Java is a dynamically linked language where the compiler doesn't necessarily have the entire program at compile time. The class compiled at one time might be combined with classes compiled at another time and place, and the entire program should still work correctly.
/L
 Signature Lasse Reichstein Nielsen - lrn@hotpop.com DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html> 'Faith without judgement merely degrades the spirit divine.'
Tim Smith - 30 Dec 2007 20:03 GMT > > It depends on how sneaky the compiler wants to be. If it notices that > > this code is only called once, couldn't it generate the random number at [quoted text clipped - 3 lines] > of the general problem, the compiler doesn't know how many times the > program will be run. Why would it matter how many times the program is run? I don't see anything (although I didn't do a deep search) in the documentation of Math.random() that says the first value returned across different runs of the programs must satisfy any particular distribution requirements.
 Signature --Tim Smith
Patricia Shanahan - 30 Dec 2007 20:17 GMT >>> It depends on how sneaky the compiler wants to be. If it notices that >>> this code is only called once, couldn't it generate the random number at [quoted text clipped - 7 lines] > Math.random() that says the first value returned across different runs > of the programs must satisfy any particular distribution requirements. The Math.random() documentation says "When this method is first called, it creates a single new pseudorandom-number generator, exactly as if by the expression
new java.util.Random
This new pseudorandom-number generator is used thereafter for all calls to this method and is used nowhere else."
The java.util.Random documentation says that the parameterless constructor "sets the seed of the random number generator to a value very likely to be distinct from any other invocation of this constructor." The algorithms for generating the streams of numbers from the seed are fully documented.
I don't see how a compile-time selection could conform to that contract, because it would act as though seed were the same for every invokation of the java.util.Random constructor.
Patricia
Tim Smith - 31 Dec 2007 04:37 GMT > > Why would it matter how many times the program is run? I don't see > > anything (although I didn't do a deep search) in the documentation of [quoted text clipped - 19 lines] > because it would act as though seed were the same for every invokation > of the java.util.Random constructor. Is that talking about different invocations within a program, or across all programs? I see they've changed the documentation since 1.4. In 1.4, it used the millisecond time as the seed, so two separate programs starting at the same time could get the same seed. The later documentation just says very likely to be distinct and doesn't give details.
Given that it is a 48 bit seed, if they do it at random, then about every 16 million times, there would be a duplicate seed (birthday paradox argument on 2^48). If they initialize partially with random and partly with something derived from time, collisions from programs launched apart in time would be less likely, but among all being launched near in time, they would be more likely.
Given a 48 bit seed, I'd be a bit surprised if they mean that it is is very likely to be globally distinct. I'd expect the problem they were trying to address with a new seeding procedure was the problem of invocations from within the same program getting the same seed. Imagine an adventure game, say, that wants to give each computer-controlled character its own random generator (that makes debugging easier, as you can reproduce the sequence) rather than have them all share one, and it happens to initialize them all within the same millisecond. That could be a problem, so I can see that they'd want to fix that.
Anyway, it's a fun problem to think about.
 Signature --Tim Smith
Patricia Shanahan - 31 Dec 2007 05:13 GMT >>> Why would it matter how many times the program is run? I don't see >>> anything (although I didn't do a deep search) in the documentation of [quoted text clipped - 32 lines] > launched apart in time would be less likely, but among all being > launched near in time, they would be more likely. The new initialization uses the sum of a long counter and System.nanoTime(). I think it would be practically impossible to get duplication within a single JVM.
I would accept something happening once in 2^48 times as "very unlikely", but not something happening every time. Indeed, the use of time seems pointless if the intent of the Random API is to allow it to produce the same sequence for each run.
Patricia
Mark Rafn - 26 Dec 2007 23:08 GMT Homework? Hate to encourage posting your class questions, but these come up occasionally to non-school seekers of language design.
>1) With dynamic polymorphism, calls to actual methods are resolved at >run time. So why is that so important? Why is that so much better >than letting the compiler figure out which version of method to call >( based on the type of object being referred by reference variable )? 1a) Because the compiler cannot know what the runtime environment will be, and what class implementations will be loaded.
1b) The compiler DOES decide this. Not the java->bytecode compiler, but the bytecode->machine just-in-time compiler that implements the runtime. And it re-decides as things change.
>Result would still be the same ... if superclass variable referred to >child class object, then method of child class object would be >called! It can change between compiliation and runtime. Heck, it can change during runtime.
>2) Why isn't polymorphism also enabled for resolving calls to static >methods? Wouldn't there be some benefits by allowing that? How would it work? Static methods have no object reference, so there are never multiple different possibilities. -- Mark Rafn dagon@dagon.net <http://www.dagon.net/>
failure_to@yahoo.co.uk - 27 Dec 2007 23:27 GMT hello
> Homework? Hate to encourage posting your class questions, but these come up > occasionally to non-school seekers of language design. > > Mark Rafn da...@dagon.net <http://www.dagon.net/> Chances are you prob won't read this post, but still...
I'd appreciate if you don't assume too much about the nature of my questions since people on this forum may start to believe you and decide not to help me and then I'm f*****. At least this way I can get a fair chance of getting people to help me when I can't figure out the stuff on my own. Try to see this from my perspective
BTW-I'm not in any school and thus I'm learning programming by myself and for myself, and if I get stuck on some topic, this group is my best chance ( contrary to your belief, I don't have a professor I can run to for help )
I hope I haven't offend you with my little rant, since that wasn't my intention
thank you all for your kind help
cheers
Mark Rafn - 28 Dec 2007 00:16 GMT >> Homework? Hate to encourage posting your class questions, but these come up >> occasionally to non-school seekers of language design.
>Chances are you prob won't read this post, but still... >I'd appreciate if you don't assume too much about the nature of my I usually read direct followups to my posts. I didn't mean any offense, and I did, in fact, both state that it might not be homework AND give my answer. Mostly I wanted to let folks know that it might NOT be homework, to avoid the common "we don't answer homework" one-liners...
Anyway, what did you think of the answers? Make sense? Raise other questions? -- Mark Rafn dagon@dagon.net <http://www.dagon.net/>
failure_to@yahoo.co.uk - 28 Dec 2007 22:58 GMT hello
* I must first point out that I realize ( even when I first started this thread ) that with the help of polymorphism we can get a generic interface and thus don’t have to change a code when new subclass is introduced!
1) Now what is most bugging me about polymorphism is the following:
I also realize, that with polymorphism we can run a program and while program is already running, we can introduce a totally new class ( let us call this new class N_C ) and thanx to polymorphism this program may operate on instances of N_C without the need to recompile or even without the need to restart this program.
But how to write a code for this program in such flexible way that program will KNOW that new class is present and operate on it is beyond me. Let me explain what I mean:
Say we have superclass A and bunch of subclasses ( all of them override A’s method a1() ). Now somewhere in this program is a code that calls a1() via reference variable ref_var:
* A ref_var; // here we define ref_var
* At some point in a program we assign to ref_var a reference to some object ( this object might be of class type A or one of its subclasses )
*then we call ref_var.a1(); // which method to actually call is resolved at runtime
Say we start this app and while app is already running, we write a new class called N_C. The already running app has to be flexible enough to enable an object of type N_C not only to be added to running app ( without even restarting this app ), but to actually use this object. But how do we do that? Let me explain it further:
Say this running app has an object of type B, where B is subclass of A, and if I want ref_var to reference this object, then I do this by writing in program code the following line:
B b = new B(): ref_var = b;
The above lines are hard coded into program. But how do we assign ref_var a reference to object of type N_C, if we introduce this new class to already running app --> somewhere in the program code the following two lines would have to be written:
N_C n_c = new N_C(); ref_ver = n_c;
But problem is app is already running and we don’t want to stop this app to write the above two new lines and yet we want this app to somehow use this new object ( by assigning ref_var a reference to n_c ). Now how can assign ref_var a reference to object of type N_C without adding the above two lines into code ?
> Anyway, what did you think of the answers? Make sense? Raise other > questions? > -- > Mark Rafn da...@dagon.net <http://www.dagon.net/> Perhaps I shouldn't say this, cos you went through so much trouble in order to help me, but truth be told questions were a bit too technical for me and even if I did somewhat understand what ( some of ) you were saying, I didn’t understand why would arguments you provided prove anything ( at least I didn’t find them to prove anything, but then again, I'm not exactly ...). But I do know that in time ( when I get a bit better in programming ) these answers will be of great value
I will give just a few examples:
>> 1) With dynamic polymorphism, calls to actual methods are >> resolved at run time. So why is that so important? Why is that [quoted text clipped - 11 lines] >Rabbit method. Java does not know to use the specialised Rabbit >method at compile time. Why couldn’t java know at compile time what to do with rabbit method? Perhaps because creators of Java decided compiler doesn’t have to know that, since, afteral, they were gonna implement dynamic binding, or is it in general not possible for compiler to know that, even if creators of Java wanted for compiler to know that?
> Please explain how the compiler can figure out which class' > method to call in > Number n = (Math.random() < 0.5) > ? new Integer(42) : new Double(42.0); > String s = n.toString(); // Integer's toString, or Double's? I don’t understand how this proves anything? Perhaps if this was done at compile time, then internally ( I’m talking out of my arse now ) there could be another
if ( n is integer then call n.toString(Integer n) ) else ( else if n is double then call n.toString( Double n ) )
statement that enable the compiler to "call" the appropriate method.
>>Result would still be the same ... if superclass variable >>referred to child class object, then method of child class >>object would be called! > >It can change between compiliation and runtime. Heck, it can >change during runtime. What can change?
BTW - I do realize that compiler can’t resolve method calls due to Java ability of introducing new classes to program ( without the need to recompile a program ) thus compiler has no way of knowing what classes may be added to program in the future ( the questions I originally asked ignored on purpose this Java ability )!
uh
Lew - 29 Dec 2007 01:56 GMT > I also realize, that with polymorphism we can run a program and while > program is already running, we can introduce a totally new class ( let [quoted text clipped - 5 lines] > program will KNOW that new class is present and operate on it is > beyond me. Java has basically three ways to accomplish this: classloaders, reflection and the debugger API.
All three are advanced topics. Let me give just the briefest summary.
Classloaders can be directed to reach out to a known source and load the bytecode for a class while the program is running.
Reflection lets a program retrieve instances from classes not known until run time, perhaps ones that have been retrieved through a custom classloader.
The debugger API has hooks that let a program substitute different class versions for each other while the program is running.
Didn't catch who said:
>> You can get a more accurate match. If a reference is an Object >> but the object itself is a Rabbit, you can get the specialised >> Rabbit method. Java does not know to use the specialised Rabbit >> method at compile time.
> Why couldn’t java know at compile time what to do with rabbit method? That's "Java", not "java".
This was explained a few times in this thread. It's not what "Java" knows, it's what the variable type is, that determines what methods the variable can call. Remember from upthread that variables have compile-time type, objects have run-time type.
> Perhaps because creators of Java decided compiler doesn’t have to know > that, since, afteral, they were gonna implement dynamic binding, or is > it in general not possible for compiler to know that, even if creators > of Java wanted for compiler to know that? No need to get religious - the creators of Java have nothing to do with this.
Java is defined by a set of rules, and those rules determine the behavior. The key is to remember that variables have only compile-time type - objects have run-time type. The variable knows how to ask for something in the compile-time type, e.g., "x.run()" for a variable "x" of type "Runnable". Since there is no information in the compiler about the run-time type of the actual object, it is only valid to say that "x" calls its "run()" method. The actual object at run time will pick up the request for a "run()" and simply use its own method to do it. That's all.
>> Please explain how the compiler can figure out which class' >> method to call in [quoted text clipped - 5 lines] > at compile time, then internally ( I’m talking out of my arse now ) > there could be another The whole point is that the compiler only knows that the variable 'n' is a 'Number'. No more is needed, actually.
At run time, the object will pick up the call to toString(), and use its own version of toString() to fulfill the call, is all.
> if ( n is integer then call n.toString(Integer n) ) > else ( else if n is double then call n.toString( Double n ) ) No need for that when the object itself already knows how to toString() itself. It's called separation of concerns, and encapsulation. The calling method doesn't need to care about the details - it just trusts the object to call its own method on its own.
> statement that enable the compiler to "call" the appropriate method. Compilers don't call methods, objects do. Compilers just tell the object which method to call.
>>> Result would still be the same ... if superclass variable >>> referred to child class object, then method of child class >>> object would be called! How would a compiler know what object is in play in the future?
>> It can change between compiliation and runtime. Heck, it can >> change during runtime. > > What can change? The object that is asked to perform the method can change.
> BTW - I do realize that compiler can’t resolve method calls due to > Java ability of introducing new classes to program ( without the need > to recompile a program )迳 thus compiler has no way of knowing what > classes may be added to program in the future ( the questions I > originally asked ignored on purpose this Java ability )! This has nothing to do with polymorphism. Polymorphism is simply that the object decides for itself how to execute a method.
 Signature Lew
twerpinator@gmail.com - 31 Dec 2007 19:05 GMT > failure...@yahoo.co.uk wrote: > > I also realize, that with polymorphism we can run a program and while [quoted text clipped - 9 lines] > Java has basically three ways to accomplish this: classloaders, reflection and > the debugger API. And one method that is relatively "nice", using a fairly simple subset of reflection, is serialization.
Say you have a plugin architecture with, say, pluggable codecs. You employ the strategy pattern and create a Codec interface that has encode() and decode() methods, among others, and supply some implementations. But you also provide code that runs at startup or when a user picks "Scan for plugins" from a menu that looks in a / plugins directory someplace looking for ".codec" files, which are actually serialized instances of Codec objects. It reads these one by one with an ObjectInputStream and casts each to Codec; if a ClassCastException is thrown, it's ignored and so is the object that was loaded; same if any of the various serialization exceptions or IOExceptions are thrown. NoClassDefFound? Discard. ObjectStreamException? Discard. The surviving objects are added to the collection of Codec objects the program maintains. Perhaps there's an initialize() method on these, and the ones that are newly added (using a Set allows detecting which are really new) get this run, adding particular "Save As" options that go through their respective encode() methods. Perhaps the program tries to decode files opened with "Open" by invoking each one's "decode()" in turn until one of them returns something other than null (or doesn't throw some exception); the new ones now get a crack at decoding any opened file.
This requires, on the programmer's part, no nastier reflection code than code to deserialize objects (and, in some SDK somewhere, to serialize them so plugins can be made). A plugin's installation requires only that some .class files (perhaps wrapped in a .jar) go into the application's classpath and a .codec file go in the application's plugins directory. Likely that plugins directory is on the app's class path and contains the plugin classes as well.
A .codec missing a needed .class will result in some sort of deserialization exception; that particular one should probably trigger a warning to the user, since it likely resulted from a sloppy installation. A user adding a plugin and getting a silent failure of anything new to appear in the program's menus will be much less able to diagnose and fix the problem than one told that they forgot to install one of the plugin's files (or the plugin's installer did).
It shouldn't be hard to generalize the above far beyond codecs to all sorts of other plugin architectures.
The dynamic polymorphism here is of course in any of the instance method calls through the Codec interface, and here can call code added while the program is already running.
Owen Jacobson - 31 Dec 2007 21:47 GMT On Dec 31, 11:05 am, twerpina...@gmail.com wrote:
> > failure...@yahoo.co.uk wrote: > > > I also realize, that with polymorphism we can run a program and while [quoted text clipped - 41 lines] > application's plugins directory. Likely that plugins directory is on > the app's class path and contains the plugin classes as well. The Java Beans specification uses the extension ".ser" for this and provides some hooks in the .jar format and java.beans API for finding and loading serialized bean instances. See sections 10.3 and 11.8 of the spec: <http://java.sun.com/products/javabeans/docs/spec.html>
and the related API docs: <http://java.sun.com/javase/6/docs/api/java/beans/ Beans.html#instantiate(java.lang.ClassLoader,%20java.lang.String)>
and the Java-Bean MANIFEST.MF entry described in: <http://java.sun.com/javase/6/docs/technotes/guides/jar/jar.html>
-o
nebulous99@gmail.com - 03 Jan 2008 20:02 GMT > The Java Beans specification uses the extension ".ser" for this and > provides some hooks in the .jar format and java.beans API for finding [quoted text clipped - 5 lines] > <http://java.sun.com/javase/6/docs/api/java/beans/ > Beans.html#instantiate(java.lang.ClassLoader,%20java.lang.String)> Haven't bothered with Beans much, but it sounds similar. Perhaps a bit more complex to do/use but perhaps a bit more powerful in exchange; it looks like you need to muck about explicitly with classloaders.
Patrick May - 29 Dec 2007 03:48 GMT > 1) Now what is most bugging me about polymorphism is the following: > [quoted text clipped - 7 lines] > program will KNOW that new class is present and operate on it is > beyond me. Let me explain what I mean: Here's a simple example:
http://www.spe.com/Chain_of_Responsibility.html
Does that help?
Regards,
Patrick
------------------------------------------------------------------------ S P Engineering, Inc. | Large scale, mission-critical, distributed OO | systems design and implementation. pjm@spe.com | (C++, Java, Common Lisp, Jini, middleware, SOA)
Lew - 28 Dec 2007 00:23 GMT > At least this way I can > get a fair chance of getting people to help me when I can't figure out > the stuff on my own. Try to see this from my perspective You will note that your post got many useful answers by several people who made no overt assumptions about your purpose.
 Signature Lew
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|