JS++ | Static vs. Dynamic Polymorphism
Last Updated :
30 Aug, 2018
Static polymorphism is polymorphism that occurs at compile time, and dynamic polymorphism is polymorphism that occurs at runtime (during application execution).
An aspect of static polymorphism is early binding. In early binding, the specific method to call is resolved at compile time. (JS++ also supports late binding via virtual functions which we will cover later.) Early binding is faster because there is no runtime overhead. Early binding is the default behavior and most common for JS++. If you want late binding, you have to explicitly specify it. Again, we'll cover late binding in a later section.
In our code, we specified the 'overwrite' modifier for our 'Cat' and 'Dog' class render() methods. This enabled method hiding, but it specifies early binding. Here's the code from Cat.jspp:
overwrite void render() {
$element.attr("title", _name);
super.render();
}
Later, when we changed the type of our cats to 'Animal' in main.jspp, the type of our cats was changed from 'Cat' to 'Animal'. You might say, "Yes, but we instantiated our cat objects using the 'Cat' class nonetheless." While this is true, it also means our cat variables can now accept data of any type satisfying the 'Animal' constraint (including 'Animal' itself if we didn't specify a protected constructor on 'Animal'). For example, this now becomes completely acceptable code:
import System;
import Animals;
Animal cat1 = new Cat("Kitty");
if (Math.random(1, 10) > 3) {
cat1 = new Dog("Fido");
}
cat1.render();
Ignore the 'System' import, but it imports the Math.random() function. It's used for illustrating the example. I also purposefully kept the name of our variable as 'cat1' to illustrate the point. 'cat1' has type 'Animal'. Thus, all objects of type 'Animal' can be assigned to 'cat1' (including objects of type 'Dog').
If you actually compile, run the code above, and refresh sufficiently, you'll notice that your "cat" will sometimes be rendered as a dog.
As you can observe, when we have a type 'Animal', the data can be 'Cat' in our program or it can also randomly become a 'Dog' based on runtime random number generation. The random numbers are not generated at compile time. The random numbers are generated during application execution (runtime). Thus, from the compiler's perspective, if we are going to resolve the 'render' method, we are going to resolve it to the 'render' method of the user-specified type, 'Animal', because it is the most correct. Recall that in subtyping, all Cats and Dogs are Animals, but not all Animals are Cats and Dogs.
Thus, this should hopefully help you understand early binding and static/compile-time polymorphism.
Aside: Data Types as Specifications
Data types are also specifications. We are specifying what constitutes a correct program. For instance, you wouldn't specify a 'subtract' function to accept two parameters of type 'string'. In our case, if we wanted a cat, we should have specified the type 'Cat' rather than generalizing to 'Animal'. While the ability to express algorithms in more general terms is desirable, it may not always be correct.
Technically, the program is still type-correct. In both cases ('Cat' and 'Dog'), we have an object of type 'Animal'. It just happens that our 'Animal' was named 'cat1' so one potential fix for the code above may be to rename the variable to 'animal' or something similar to express our intent.
The other potential fix, if we want 'cat1' to always be a cat, is to restrict the data type to 'Cat' instead of 'Animal'. If you do this, you'll get a compile error because 'Dog' is not a subtype of 'Cat':
JSPPE5000: Cannot convert `Animals.Dog' to `Animals.Cat' at line 6 char 8 at main.jspp
In runtime polymorphism, the type is determined at runtime. For example, we can use the 'instanceof' operator to check the runtime data type. Change your main.jspp file and observe the result:
import System;
import Animals;
external $;
Animal animal = new Cat("Kitty");
if (Math.random(1, 10) > 3) {
animal = new Dog("Fido");
}
if (animal instanceof Cat) {
$("#content").text("We have a CAT.");
}
else {
$("#content").text("We have a DOG.");
}
Keep refreshing and you should see that sometimes we have a 'Cat' instance and sometimes we have a 'Dog' instance. However, the types (and resulting messages) are determined at runtime — not compile time.
Similar Reads
JS++ | Subtype Polymorphism Subtyping describes type relationships, and subtype polymorphism enables operations defined for supertypes to be safely substituted with subtypes. Concretely, imagine the relation between a 'Cat' class and an 'Animal' class. (Remember: classes create data types in JS++.) In this case, within the con
3 min read
JS++ | Static Members and "Application-Global" Data Up until now, all of the fields and methods that we've declared have belonged to class instances. Static members can also be added to a class. A static member is initialized at program start and is available to all instances of a class. As an example, we might want to keep a count of the number of '
4 min read
JS++ | Classes, OOP, and User-defined Types Up until now, we've been declaring variables, looping over data, and writing 'if' and other conditional statements. These operations comprise the "imperative programming" paradigm where we describe "how" a program operates step by step (or, more specifically, statement by statement). Oftentimes, in
6 min read
JS++ | Upcasting and Downcasting Now that we understand both subtyping and static versus dynamic polymorphism, we can learn about upcasting and downcasting. Upcasting and downcasting is based on type relationships. In other words, if you have data of type 'Animal', you can "downcast" it to its subtype 'Dog'. Conversely, if you have
3 min read
JS++ | Access Modifiers and 'super' Access modifiers allow us to change the "visibility" and "access privileges" of a class (or module) member. These are best understood by example. JS++ has three access modifiers: private, protected, and public. A private member is the least permissive. If a member is declared as 'private' it can onl
15 min read