Last active
January 28, 2020 06:13
-
-
Save 6abe/11291304 to your computer and use it in GitHub Desktop.
Is inheritance essential to support polymorphism?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Is inheritance essential to support polymorphism? To answer the | |
question, understanding of the difference between inheritance and | |
polymorphism is necessary. | |
Inheritance is when one object or class is based on another class for | |
code reuse. This way the child or derived classes would not have to be | |
implemented with the same code. Inheritance is useful when you want to | |
substitute an instance of a derived class in place of an instance of a | |
base class. In static languages, this is where the confusion begins, but | |
let's skip this for now and we will come back to it when we see some code! | |
Polymorphism on the other hand is essentially the binding of a method | |
call at runtime instead of compile time. This allows for greater | |
extensibility in the code. | |
Ok, now let's see some code! | |
Suppose we have three objects that fly and we want to be able to put all | |
three objects in an array and call a fly method on them. | |
Polymorphism with Inheritance in Java: | |
import java.util.*; | |
public class Main { | |
interface Flyer { | |
public String fly(); | |
} | |
public static void main(String [] args) { | |
class Bird implements Flyer { | |
public String fly() { return "It's a " + | |
this.getClass().getSimpleName() + | |
"."; } | |
} | |
class Plane implements Flyer { | |
public String fly() { return "It's a " + | |
this.getClass().getSimpleName() + | |
"."; } | |
} | |
class Superman implements Flyer { | |
public String fly() { return "No, it's " + | |
this.getClass().getSimpleName() + | |
"!"; } | |
} | |
ArrayList<Flyer> thingsThatFly = new ArrayList<Flyer>( | |
Arrays.asList( new Bird(), new Plane(), | |
new Superman() )); | |
for( Flyer thing:thingsThatFly ) System.out.println( thing.fly() ); | |
} | |
} | |
output: | |
It's a Bird. | |
It's a Plane. | |
No, it's Superman! | |
In this example, we make an interface Flyer with a method called fly | |
and let all flyer type objects inherit from it. We then create an array of | |
Flyer objects and iterate through them calling the fly method. | |
Looking at this example, it appears inheritance is necessary to use | |
polymorphism because we have to preserve static type checking. We must | |
create a Flyer interface and our classes must inherit from that interface | |
to conform to typed parameters of the for loop. | |
In Java our code design will be more of a design by contract since we | |
must conform to the static type system in the language. Does this issue | |
between inheritance and polymorphism begins is only in statically typed | |
languages? Let's see an example in a dynamic language and find out! | |
Polymorphism without Inheritance in Ruby: | |
class Bird | |
def fly | |
"It's a #{self.class}." | |
end | |
end | |
class Plane | |
def fly | |
"It's a #{self.class}." | |
end | |
end | |
class Superman | |
def fly | |
"No, it's #{self.class}!" | |
end | |
end | |
things_that_fly = [ Bird.new, Plane.new, Superman.new ] | |
things_that_fly.each { |thing| puts thing.fly } | |
output: | |
It's a Bird. | |
It's a Plane. | |
No, it's Superman! | |
In the Ruby example, there is no inheritance being used. The puts | |
method calls fly on each of the elements in the things_that_fly array. Ruby | |
doesn't care what object is being passed as long as they all respond to | |
fly method. If they don't, Ruby will throw a runtime exception. In Ruby, | |
we don't want to limit ourselves to a contract of types; we want to be | |
able to pass anything as long as the object responds to the fly method. | |
Thus, dynamic languages use a design by capability approach. | |
Due to the design differences of static and dynamic languages we must | |
approach problems differently. In static languages, we must conform to | |
types leading to a design by contract. In dynamic languages, we can use | |
a design by capability. This is key difference is instrumental in why | |
inheritance is essential to support polymorphism in static typed languages | |
such as Java and not in dynamic languages like Ruby. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment