Polymorphism in Perl comparing with JAVA and C++

Polymorphism in Perlcomparing with JAVA and C++

Abstract

In USD daily test automation, we used Perl as programminglanguage a lot. When talking about Perl, many people still see it in this way: “itis a scripting language, good at handling strings and text”. But after wepractice more and more using Perl programming, we found this traditional viewof Perl language only reflect very little part of Perl’s capability and designconcept. In this article, you will see how Perl as a programming languagesupports Polymorphism in a very flexible way; some examples will be given also.

What is Polymorphism?

Polymorphism in one sentence can be explained as this:  is the ability to create a variable, afunction, or an object that has more than one form [1]. If this explanation isstill too vague, we can draw it as following:

  

    


Figure 1: Varieties of polymorphism[2]

There are two majorkinds of universal polymorphism, i.e., two major ways in which a value can havemany types:

 

 In parametric polymorphism, a polymorphicfunction has an implicit or explicit type parameter, which determines the typeof the argument for each application of that function. The functions thatexhibit parametric polymorphism are also called generic functions. A genericfunction is one which can work for arguments of many types, generally doing thesame kind of work independently of the argument type. If we consider a genericfunction as a single value, it has many functional types and is thereforepolymorphic.

 

 In inclusion polymorphism an object can beviewed as belonging to many different classes which need not be disjoint, i.e.there may be inclusion of classes.

 

 These two views of universal polymorphism arenot unrelated, but are sufficiently distinct in theory and in practice todeserve different names. 

 

There are also two majorkinds of ad-hoc polymorphism. Method overloading refers to methods that havethe same name but different signatures inside the same class. Coercion isinstead a semantic operation which is needed to convert an argument to the typeexpected by a function, in a situation which would otherwise result in a typeerror. Coercions can be provided statically, by automatically inserting thembetween arguments and functions at compile time, or may have to be determineddynamically by run-time tests on the arguments.

 

In this article, we willfocus on universal polymorphism implementation in 3 languages only. For ad-hocpolymorphism in Perl, for Perl 5.x: please refer to CPAN overload module, for Perl6: please refer to ‘multi’ grammar [3]. Also you can quick think about thefollowing code output to get the idea of ad-hoc polymorphism:

 

$a = 3.2;

$b = '2.4';

$num = $a + $b;

$str = $a.$b;

print $num;

print $str;

 

How different language align to these concepts

Let’s review the one sentence definition to polymorphism: theability to create a variable, a function, or an object that has more than oneform. This definition actually has no context at all, because it mentioned variable(every programming paradigms will have variable), function (basic concept in declarativeprogramming paradigms), object (usually mentioned in OO programming paradigms).So, here I want to emphasize one thing: Polymorphism is a concept not onlyexisting in OO context! Just because inclusion polymorphism usually implementedthrough multi inheritance, it doesn’t mean it must belong to OO.

Take following scenario as examples in programming context: Giveyou a dog, please make it sometimes a live animal and sometimes a toy dog. Adog could be an animal, if it is a live dog, as an animal, a dog could bark,sleep and be feed. But it could also be a toy, if it is made by plastic! As atoy, a dog could also bark, but will not sleep, and will eat nothing! How couldwe define classes and instantiate objects to satisfy above scenario indifferent context?

Inclusion polymorphism in JAVA

In JAVA, there are two important grammars key word: ‘abstract’and ‘interface’. JAVA define its language to include ‘abstract’ and ‘interface’both just because JAVA think multi-inheritance is evil! JAVA believes one classcan only have one super class or parent class. So, a dog can be a sub class ofAnimal, but it can’t have another parent called ‘Toy’ at the same time. So itdefines ‘interface’ to give dog the capability to become a toy, if it implementsthe ‘Toy’ interface.

So, in JAVA, we will define an abstract class called Animalwith abstract methods defined like makeNoise(), sleep(),eat(),walk(). Thendefine an interface called Toy with makeNoise() and walk() and dance() – a toydog may know how to danceJThen you have your dog class to inherit from Animal, you can override makeNoise()and walk() to make it look more like a dog; then you need to implement the Toyinterface also to fill content with Toy’s makeNoise() and dance() methods. Theyyour dog object can sometimes eat like an animal and sometimes dance like a toywhen context is given.

Inclusion polymorphism in C++

In C++ world, multi-inheritance is accepted, that is why we willonly see ‘virtual’ grammar in C++ language, and it gives user the capability todefine abstract object and methods.

So, with C++, we can indicate a dog class as both Animal’ssub class and Toy’s sub class. Both Animal and Toy are virtual classes with onlyvirtual functions defined. Dog class can choose override some of its parents’methods to make specific behavior of Dog.

Inclusion polymorphism in Perl

Now let’s look at Perl and see how it could deal with thissituation. The answer is very simple, using ‘bless’. So for above example, actually,we only need to define 2 classes in Perl, you just need to define one Animalclass and one Toy class and do not need to care about those  confusing concept defined in JAVA and C++like; ‘abstract’, ‘virtual’, ’interface’, etc. The only thing you need to dothen is bless your object to Animal or Toy when you want to!

But why Perl can achieve this? The answer is that Perl is aweak-typed language not like JAVA and C++ as strong-typed language. In OOcontext, we can generalize the meaning of Type to class also. Each Class is akind of data type, each instance of that class has the same type. In JAVA and C++,once the Class is defined, one new type is created and can’t be changed duringprogram run time. Things are totally different in Perl 5, because firstly, thisis no Class grammar actually in Perl; anything could be a Class or Object onceyou ‘Bless’ it as following code:

$str = 'a';

$strRef = \$str;

bless($strRef,'anything');

print ref($strRef);#output is ‘anything’

bless($strRef,'anything else');

print ref($strRef); #output is‘anything else’

 

Which means Perlgives you the capability to mark any reference to any namespace during the runtime! In above example, ‘anything’ and ‘anything else’ could be some existing package(class) so that the reference immediately gets the rights to call methodsdefined in that package! This is another thing Perl is totally different fromJAVA and C++, because there is no such kind of grammar like ‘public’, ‘private’,‘protected’ defined  to strictly protectyour data structure.

 

Please see following codes:

1.       package animal;

 

2.       sub new

3.      {

4.      $class = shift;

5.      $self = { 'name' => shift,

'category' => shift

};

6.      bless($self,'animal');

7.      return $self;

8.      }

9.      sub walk

10.  {

11.  $self = shift;

12.  print "I am: $self->{name}walking as an animal..\n";

13.   }

 

14.   sub speak

15.  {

16.  $self = shift;

17.  print "I am: $self->{name}speaking as an animal..\n";

18.   }

 

19.   1;

 

20.   package toy;

 

21.   sub new

22.  {

23.  $class = shift;

24.  $self = { 'name' => shift,

'brand' => shift,

};

25.  bless($self,'toy');

26.  return $self;

27.   }

 

28.   sub walk

29.  {

30.  $self = shift;

31.  print "I am: $self->{name}walking as a toy, very fast..\n";

32.   }

 

33.   sub speak

34.  {

35.  $self = shift;

36.  print "I am: $self->{name}speaking as an toy..\n";

37.   }      

 

38.   1;

 

39.   package monster;

 

40.   sub kill

41.  {

42.  print "I am a monster, I amkilling you..\n";

43.   }

 

44.   1;

 

 

45.   $dog = {};

46.  bless($dog, 'animal');

47.   $dog->speak();

 

48.   $dog->{'name'} = 'jack';

49.   $dog->speak();

 

50.   bless($dog, 'toy');

51.  $dog->speak();

52.   $dog->walk();

 

53.   bless($dog, 'monster');

54.   $dog->kill();

 

55.   *{monster::cry} = sub { print "I am a monster, no one lovesme...\n" };

 

56.   $dog->cry();

 

The output is like:

I am:  speaking as an animal..

I am: jack speaking as an animal..

I am: jack speaking as an toy..

I am: jack walking as a toy, very fast..

I am a monster, I am killing you..

I am a monster, no one loves me...

 

See themagic here? In above example, in line 53, I just defined an empty hashreference, then I bless it to ‘animal’, it can speak immediately in line 55even without a name! Then I dynamically give it a name in line 56, and callspeak again, this time, it is still an animal, so it speaks like an animal. ThenI bless it to ‘toy’, now, it speaks like a toy. Same thing happened after Ibless it to ‘monster’ in line 60, it now can kill others! But the most magicthing is that I can dynamically defined a new method and insert it into ‘monster’package and they my dog can cry as a monster in line 63! After writing abovecodes, you will feel good like a God, because you can bless anything toanything! God Bless youJ

 

Based onabove behaviors, you can see Perl is implementing inclusion polymorphism in avery flexible way, you can modify a class’s attributes and methods on the flyduring run time, and this will never be a goal for strong-typed language likeJAVA and C++. Definitely, this is totally not safe to a data structure, but itis not Perl’s concern, because Perl’s spirit is: won’t limit the way you dothings.

 

Then, howabout ‘parametric polymorphism’?  

Parametric polymorphism in JAVA

Java parametric polymorphism is called generics andimplemented through type erasure. This design decision was made toensure backwards compatibility and ensure that Java generics are interoperablewith non-generic code. So usually in JAVA, you can see container or aggregatoris usually implemented using the ‘generic’ concepts.

Parametric polymorphism in C++ [4]

C++ uses templates to enable generic programming techniques.The C++ Standard Library includes the Standard Template Library or STL thatprovides a framework of templates for common data structures and algorithms.Templates in C++ may also be used for template meta-programming, which is a wayof pre-evaluating some of the code at compile-time rather than run-time. Usingtemplate specialization, C++ Templates are considered Turingcomplete.

There are two kinds of templates: function templates andclass templates. A function template is a pattern for creating ordinaryfunctions based upon the parameterizing types supplied when instantiated. Forexample, the C++ Standard Template Library contains the function template max(x,y) which creates functions that return either x or y, whicheveris larger. max() could be defined like this:

template

T max(T x, T y)

return x < y ? y : x; }

 

Specializations ofthis function template, instantiations with specific types, can be called justlike an ordinary function:

 

cout << max(3, 7);   // outputs 7

The compiler examines the arguments used to call max anddetermines that this is a call to max(int, int). It then instantiates aversion of the function where the parameter zing type T is int,making the equivalent of the following functions:

int max(int x, int y) { return x

This works whether the arguments x and y areintegers, strings, or any other type for which the expression x < y issensible, or more specifically, for any type for which operator< isdefined. Common inheritance is not needed for the set of types that can beused, and so it is very similar to duck typing. A program defining a custom datatype can use operator overloading to define the meaning of < forthat type, thus allowing its use with the max() function template.While this may seem a minor benefit in this isolated example, in the context ofa comprehensive library like the STL it allows the programmer to get extensivefunctionality for a new data type, just by defining a few operators for it.Merely defining < allows a type to be used with the standard sort(), stable_sort(),and binary_search() algorithms or to be put inside data structuressuch as sets, heaps, and associative arrays.

C++ templates are completely type safe atcompile time. As a demonstration, the standard type complex does notdefine the < operator, because there is no strict order on complexnumbers. Therefore max(x, y) will fail with a compileerror if x and y are complex values. Likewise,other templates that rely on < cannot be applied to complex dataunless a comparison (in the form of a functor or function) is provided. E.g.:A complex cannot be used as key for a map unless acomparison is provided. Unfortunately, compilers historically generate somewhatesoteric, long, and unhelpful error messages for this sort of error. Ensuringthat a certain object adheres to a method protocol can alleviate thisissue. Languages which use compare instead of < can alsouse complex values as keys.

The second kind of template, a class template, extendsthe same concept to classes. A class template specialization is a class. Classtemplates are often used to make generic containers. For example, the STL hasa linked list container.To make a linked list of integers, one writes list. A list ofstrings is denoted list. A list has a set ofstandard functions associated with it, which work for any compatibleparameterizing types. The class template concept is much like the ‘generic’concept in JAVA.

Parametric polymorphism in Perl

As we mentioned before, Perl is a weak-typed scripting languagecompared to JAVA and C++,  so in PerlParametric polymorphism can be done naturedly, Perl doesn’t need to definespecific grammar like ‘generic’ in JAVA and ‘Template’ in C++. Since JAVA andC++ are strong-typed, they will check any ‘type’ inconsistency during compilingtime, so JAVA need to make sure the class type used in Iteration or Aggregationshould at least belongs to the same supper or much supper class. C++ need tomake sure the types you passed to a function template is valid to alloperations inside that function.

But for Perl, it won’t check the types you put into a listor the methods you apply to those types, in Perl, everything can be referencedand the programmer is the only one who should be responsible to the functionyou applied to those references….

More parametric polymorphism examples in Perl can be foundby function programming support in Perl, I will discuss functional programmingin Perl in another article.

Summary

Why ‘Polymorphism’? Because we need it to provide us a capability of dynamicbinding during run time, but just because JAVA and C++ is strong-typedlanguage, they must make sure programmer is using the correct type (Class) withcorrect method during compiling time. But Perl is more flexible language, itfocus on the logic you want to apply to data type and related function withoutputting more strict check on this. This makes Polymorphism implementation easierin Perl but more error-prone also.

 

Reference:

[1] Wiki page: Polymorphism in object-oriented programming

[2] Article: On Understanding Types, Data Abstraction, andPolymorphism – Luca Cardelli & Peter Wegner

[3] Perl 6 website documents: perl6.org

[4] Wiki page: Generic programming


你可能感兴趣的:(编程语言-perl,工作心得,编程语言-java)