Upcasting in OOPS makes runtime polymorphism possible by overriding methods of parent and child classes. Can downcasting in OOPS also be run-time polymorphic in any way?
runtime polymorphism is made possible by inheritance -- upcasting and downcasting are irrelevant to it (though they are also only possible with inheritance).
Downcasting generally requires runtime polymorphism, as the downcast may succeed or fail based on the runtime type.
Related
The process in which the newly created class uses elements of a more general class of already existing is inheritance, but is this also apply to the polymorphism?. I can't find in the internet an satisfying answer.
Inheritance is derived from the overall concept of polymorphism. Inheritance would be more specifically a type of Ad hoc polymorphism. The concept of an object oriented language in general is to allow features such as inheritance and abstraction. So inheritance allows the specialization of classes in say a hierarchical manner so then subclasses may inherit from a parent or more "general class", while Polymorphism allows you to use an object without knowing its exact type such as calling an inherited or virtual method and the language being able to get the correct method from many derivations or implementations of such method.
No, Polymorphism is where two or more classes that either implement the same interface or extend the same parent can be substituted for each other.
An example is how a List and a HashTable are both Collections and may be substituted for each other when the object is defined as the general type (Collection)
Are they interchangeable terms? Would you be able to give formal definitions and also examples?
Both terms (superclass and supertype) are related, but they are not exactly interchangeable.
Only classes have superclasses, while other classifiers have supertypes. Since Class is also a Classifier, a superclass is always a supertype (because superclass redefines the general association between classifiers), but the opposite is not true.
For instance, the primitive type long in Java is defined as a supertype of int. Since primitive types are not classes, long is not a superclass of int.
Another example: in UML, components and interfaces are different from classes (all of them are classifiers), then it is not correct to say "the superclass of a component" but "the supertype of a component".
To say that A is a subclass of B merely asserts that A is formed using inheritance.
To say that a is a subtype of B asserts that A preserves the meaning of all the operations in B.
It is possible to form subclasses that are not subtypes; and (in some languages at least) form subtypes that are not subclasses.
Is there any direct relationship between Late Binding and Overriding, similarly for Early Binding and Overloading?
They (Binding/Overriding/Overloading) can be termed as ways to implement polymorphism, but is there any "Direct Relationship" ex: Late Binding is a sub/super concept to Overriding and vice versa etc?
They are orthogonal (independent) concepts.
Overloading, Overriding: Forms of polymorphism
Early binding/Late binding: In the former, the method to call is known at compile time. In the latter, at runtime.
Of course, an implementation of overriding usually implies using late binding, because you will only know the object's real type at runtime. But that's just a special case.
I've been told recently a good practice in object oriented programming that you should always allow inheritance from your classes. I really don't think so, but I have no solid arguments on my mind.
Real-world examples of blocked inheritance:
No C++ STL class (specialized class template) allows inheritance (having non-virtual destructors).
Java has its final class modifier that applies to many standard components, like java.lang.String.
Possible reasons I think are:
Security, since subclass might have access to sensitive internals. (I don't think so -- they won't access private members.)
Performance, since a subclass could mess up our efficient implementations by overriding some of the member functions. (Children won't override non-virtual functions.)
To enforce composition over inheritance. (I fully agree. We shouldn't favor inheritance when it's not needed.)
So my question is: In what circumstances should I intentionally block inheritance?
In fact, the practice that I try to follow, and that Josh Bloch recommends, in his Effective Java book, is exactly the inverse rule of the one you've been told: Unless you have thought about inheritance, designed your class to be inherited, and documented how your class must be inherited, you should always disable inheritance.
I would recommend reading this chapter of Effective Java (you won't regret buying it), and showing it to the person who told you about this rule.
The most obvious reason to disallow inheritance is immutability. An immutable object is simple to use (only one state), can be cached, shared between many objects, and is inherently thread-safe. If the class is inheritable, anyone can extend the class and make it mutable by adding mutable attributes.
Well for starters, only disallow inheritance if you are positive that you don't want others to be extending your class. Preventing inheritance for trivial reasons (such as performance) is usually not recommended, as code reuse often outweighs the small performance gains you can achieve by marking your class final.
That being said, here are several examples when you might want to explicitly prevent inheritance:
You are writing a commercial, closed-source class, and you don't want people to be able to change the functionality down the line. This is a good reason to prevent class inheritance, as you don't want to have to give support for it later on if people have overridden your methods and/or extended your classes, and are complaining that they are getting unexpected results.
You are designing an immutable class. By marking the class final, you are preventing subclasses from compromising the immutable behavior of your class. For example, if you were allowed to subclass String, others could make their own implementations that allows Strings to be modified. Now no code that takes a type String can be certain that the object is immutable.
You want to force composition over inheritance. This is desirable when you want to avoid tight coupling between classes (i.e. you don't want groups of classes that are highly dependent on one another).
You want to encourage inlining by the compiler. Marking classes and methods as final may result in small performance gains, as it will ensure that Java doesn't have to look up the right class method to invoke for an object at runtime. Non-final methods are marked as virtual so that they can be properly extended if needed, final methods can be directly linked or compiled inline in the class. Note that the performance gain you can achieve by doing this is often insignificant (especially if your class' methods are large).
Just my 0.02 on this...
Allowing inheritance on a class allows people to deal with unforeseen issues. (ex. the monkeypatching that often occurs in RoR. It can be ugly but it's reality vs. pedantry). Having said that, I'm not a big fan of gratuitous inheritance. The relationship between base and subclasses can be brittle. Deep inheritance hierarchies are hard to grok.
One case I can think of disallowing inheritance is enforcing immutability. This is important for things like the Java String class.
I'm trying to solve a design issue using inheritance based polymorphism and dynamic binding. I have an abstract superclass and two subclasses. The superclass contains common behaviour. SubClassA and SubClassB define some different methods:
SubClassA defines a method performTransform(), but SubClassB does not.
So the following example
1 var v:SuperClass;
2 var b:SubClassB = new SubClassB();
3 v = b;
4 v.performTransform();
would cause a compile error on line 4 as performTransform() is not defined in the superclass. We can get it to compile by casting...
(v as SubClassA).performTransform();
however, this will cause a runtime exception to be thrown as v is actually an instance of SubClassB, which also does not define performTransform()
So we can get around that by testing the type of an object before casting it:
if( typeof v == SubClassA)
{
(cast v to SubClassA).performTransform();
}
That will ensure that we only call performTransform() on v's that are instances of SubClassA. That's a pretty inelegant solution to my eyes, but at least its safe. I have used interface based polymorphism (interface meaning
a type that can't
be instantiated and defines the API of classes that implement it) in the past, but that also feels clunky. For the above case, if SubClassA and SubClassB implemented ISuperClass
that defined performTransform, then they would both have to implement performTransform(). If SubClassB had no real need for a performTransform() you would have to implement an empty function.
There must be a design pattern out there that addresses the issue.
My immediate comment is that your object modelling is wrong. Why treat SubClassA as a SuperClass (is-a relationship), when I would suggest that it's not.
You could implement a dummy performTransform() that does absolutely nothing in its base instance, and is overridden in SubClassA. But I'm still concerned that on one hand you're treating all these objects (SubClassA, SubClassB) as the same thing, and then wanting to treat them differently depending on their real implementation, rather than the interface they present.
Assuming you are using a strongly-typed language, which your question seems to indicate...
There is no design pattern to work around this, because this is the intended behavior.
In your definition, performTransform belongs only to SubClassA. Thus, to be able to invoke performTransform on an object, the object must be of type SubClassA (or a subtype of SubClassA.
Invoking performTransform on a SuperClass does not make sense because not every instance of SuperClass defines this method.
Downcasting from a SuperClass to a SubClassA should certainly throw an error if the instance is not a SubClassA - this should be obvious.
So, you must either change your definitions such that performTransform belongs to SuperClass (in which case, as you said, every instance of type SuperClass would need to have some implementation for the method, even an empty one) or you must make sure that you are only invoking methods on types that define them.
I'm not so sure it requires a pattern to solve but instead just a small redesign. If it makes sense for anything to call performTransform is should be in the superclass as a virtual method and overridden in the subclasses.
So the superclass defines the flow from an abstract viewpoint and the subclasses implement them appropriately. In your case, the simplest options are to either just leave performTransform empty in the superclass or implement it as an empty method in the subclass that doesn't require it (when you mix this approach with a short comment, you get a more maintainable system IMO).
The closest pattern I can think of for this is the Null Object pattern where this performTransform method is just a dummy function to preserve compatibility but perform no actual task.
Just because you say your bicycle is a car doesn't mean there's a place to put gas in it. The whole point of polymorphism is to let you think of things as the super class - these are all bank accounts, these are all shapes, to use the classic examples - and not get caught up in what they really are. Sometimes the subclasses add capability. In many cases that capability is used in the specific implementations in each subclass. So to use your names, some method Adjust() that is in the signature of SuperClass is implemented (differently) in SubClassA and SubClassB. The SubClassA version calls its own performTransform as part of the process and we all live happily ever after. The minute some code needs to decide whether to call performTransform or not, you're not just thinking of it as a SuperClass any more. That's not necessarily something that needs to be solved, it's just what is.
It Would be better to have the call to performTransform() in a method that only takes type SubClassB as a parameter - at least you wouldn't have to do type checking then.
On saying that, if your having this problem at all it may suggest that inheritance may not be the best solution - composition may be a better way to approach the problem.