W
W
wexx2017-10-15 16:22:43
Java
wexx, 2017-10-15 16:22:43

How to give a verbal example of polymorphism?

I recently had a phone interview. They asked what polymorphism is, why it is needed and asked to give an example ...
If I had no problems with the definition of polymorphism, then the question of what it is needed for baffled me ...
To shorten the code, to dynamically change the implementation .. .mmm... For what?
And with an example in general there was an embarrassment. I began to give an academic example about geometric shapes and realized that I was explaining very incomprehensibly and not "smoothly".
After the interview, of course, I began to look for a normal "verbal" example of polymorphism, as well as what it is for ... but I found only examples with code snippets. But you can’t give the code over the phone and you won’t write it ..
So the question is how to give a verbal example of polymorphism and explain "what it is for", so that he would arrange a person at the other end of the wire?

Answer the question

In order to leave comments, you need to log in

3 answer(s)
D
Daniil Kolesnichenko, 2017-10-15
@KolesnichenkoDS

There are three types of polymorphism: parametric, ad-hoc, and subtype polymorphism.
Parametric polymorphism is needed to write logic parameterized by types that implement some interfaces (a degenerate case - parameterized by any types). The simplest example is a function mapthat applies a function to each element of an array. Without polymorphism, we would write a separate function for each type:

mapIntFloat :: (Int -> Float) -> [Int] -> [Float]
mapIntFloat f [] = []
mapIntFloat f (x:xs) = (f x) : (map f xs)

mapIntString :: (Int -> String) -> [Int] -> [String]
mapIntString f [] = []
mapIntString f (x:xs) = (f x) : (map f xs)
-- и так далее

It turns out quite cumbersome and there is a repetition of logic in each function of the form mapTypeType. To avoid repeating the logic, we parameterize the function mapwith respect to the types of the original array and the resulting array:
map :: forall a b. (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = (f x) : (map f xs)

Now instead of concrete types like Intor Floatwe have type variables : aand b.
Okay, but if you dig deeper, it turns out that the same logic as mapfor arrays applies to other types as well. For example, to optional-values. Without ad-hoc polymorphism, we would write something like:
mapList :: forall a b. (a -> b) -> [a] -> [b]
mapList f [] = []
mapList f (x:xs) = (f x) : (mapList f xs)

mapMaybe :: forall a b. (a -> b) -> Maybe a -> Maybe b
mapMaybe f Nothing = Nothing
mapMaybe f (Just x) = Just (f x)

It can be seen that the logic is approximately the same everywhere, the signatures coincide up to the parameterized type. This is where ad-hoc polymorphism comes into play:
class  Functor f  where
    map :: (a -> b) -> f a -> f b

We have parameterized the logic we need relative to the parameterized type f, and now we can write implementations for specific types:
instance  Functor Maybe  where
    map f Nothing = Nothing
    map f (Just x) = Just (f x)

instance  Functor [] where
    map f [] = []
    map f (x:xs) = (f x) : (map f xs)

The function itself mapnow has a type:
Now we can write functions that work with any functors, that is, again, reduce the repetition of logic in the code.
Finally, subtype polymorphism is a slightly different approach to the previous problem. Instead of extracting a common interface, we create a base type and inherit the rest from it. In this case, it Functorwill be an abstract class with an abstract method mapfrom which types are inherited Maybe, Listand so on. In this case, the signature of a function that takes and returns a functor would look something like this: foo :: Functor Int -> Functor String.

E
eRKa, 2017-10-15
@kttotto

When you need to write something down, they usually take a piece of paper and a pen. Or maybe not a pen, you can use a pencil, you can use a felt-tip pen or a fountain pen. Polymorphism will consist in the fact that you need an object with which you can write something, and which one and how it implements the record itself does not bother you much. Those. when you say: "give me an object to write", you can slip any object that, as an abstraction, is a "pen".
When you want to sleep, you say: "give me something to lie on." And it will be possible to lie down even on the sofa, even on the bed, even on the chair-bed. Abstractly, this will all be a "bed", but the implementation will be different.
Polymorphism is convenient when, for example, there may be changes, additions to the code. Then we abstract from the specific implementation, create an abstract class, and in the method we already request an object of this type. And at runtime, we can slip an object of any other type for execution, which will be inherited from this abstract one and will have its own implementation of some methods. So yes, it's "dynamic change of implementation".

A
Alexander, 2017-10-15
@zkelo

Polymorphism for Beginners

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question