1
00:00:04,540 --> 00:00:05,450
All right so in this video,

2
00:00:05,450 --> 00:00:07,290
we're gonna look at polymorphism

3
00:00:07,290 --> 00:00:10,690
and how it's an important part of the Python philosophy.

4
00:00:10,690 --> 00:00:13,270
Now before I explain what polymorphism is,

5
00:00:13,270 --> 00:00:14,450
let's have a look at some code

6
00:00:14,450 --> 00:00:16,340
and talk about what's going on.

7
00:00:16,340 --> 00:00:18,850
So I'm still in the game project we've been working on.

8
00:00:18,850 --> 00:00:21,610
I'm gonna clear out all the code from our main programme.

9
00:00:21,610 --> 00:00:23,900
I'm just gonna copy it all, delete the lot,

10
00:00:23,900 --> 00:00:27,820
and I'm gonna start by typing in a = 3,

11
00:00:27,820 --> 00:00:30,100
b = 2 in double quotes,

12
00:00:30,100 --> 00:00:31,520
c = 1, 2, 3.

13
00:00:33,650 --> 00:00:37,840
So we've got three variables, a, b, and c.

14
00:00:37,840 --> 00:00:40,410
And I've typed x there and not c.

15
00:00:40,410 --> 00:00:41,940
So a refers to an integer,

16
00:00:41,940 --> 00:00:44,650
b to a string, and c to a topple.

17
00:00:44,650 --> 00:00:47,070
Okay so let's print them out.

18
00:00:52,300 --> 00:00:53,470
Okay let's run

19
00:00:56,530 --> 00:00:58,680
and there's no real surprises at the result

20
00:00:58,680 --> 00:01:00,560
when I run the programme.

21
00:01:00,560 --> 00:01:04,379
So what that's done is pass three total different variables

22
00:01:04,379 --> 00:01:05,930
to the print function

23
00:01:05,930 --> 00:01:08,930
and it's happily printed out a value for each one.

24
00:01:08,930 --> 00:01:11,190
So what's happening here is that each object

25
00:01:11,190 --> 00:01:14,810
is behaving in a similar way when we try to print it.

26
00:01:14,810 --> 00:01:16,260
So in addition to their behaviour

27
00:01:16,260 --> 00:01:18,400
as an int, string, or a topple,

28
00:01:18,400 --> 00:01:21,230
they also have printable behaviour.

29
00:01:23,050 --> 00:01:26,040
So a is an int and we can subtract two ints

30
00:01:26,040 --> 00:01:27,810
to work out their difference.

31
00:01:27,810 --> 00:01:31,460
B is a string and you can't subtract strings in Python

32
00:01:31,460 --> 00:01:34,170
so they are very different types of object,

33
00:01:34,170 --> 00:01:38,340
but they also share printable behaviour and in that respect,

34
00:01:39,500 --> 00:01:42,170
they behave like a different type of object,

35
00:01:42,170 --> 00:01:44,110
an object that's printable.

36
00:01:44,110 --> 00:01:47,110
Now that ability of objects to have different forms

37
00:01:47,110 --> 00:01:51,280
is called polymorphism which just really means many forms.

38
00:01:53,740 --> 00:01:55,670
Now in this particular example,

39
00:01:55,670 --> 00:01:58,340
the polymorphic behaviour of the objects

40
00:01:58,340 --> 00:02:01,080
is implemented using inheritance.

41
00:02:01,080 --> 00:02:05,220
All Python objects inherit from a base class called object,

42
00:02:05,220 --> 00:02:07,890
which defines an __str__ method.

43
00:02:11,020 --> 00:02:13,570
So polymorphism allows the print function

44
00:02:13,570 --> 00:02:15,850
to accept arguments of any type

45
00:02:15,850 --> 00:02:18,940
and it's able to then print them out.

46
00:02:20,410 --> 00:02:23,460
Now even Java programmers wouldn't be surprised at this

47
00:02:23,460 --> 00:02:26,520
because you can do the same thing in Java.

48
00:02:26,520 --> 00:02:29,440
And in fact, I'm gonna do something really strange now

49
00:02:29,440 --> 00:02:33,360
and show you some Java code in a Python course.

50
00:02:35,680 --> 00:02:38,450
So this slide shows some of the declarations

51
00:02:38,450 --> 00:02:40,540
of the Java print method.

52
00:02:41,720 --> 00:02:45,340
Now all the lines starting with asterisks are comments

53
00:02:45,340 --> 00:02:48,940
so we're interested in the lines that start public void.

54
00:02:48,940 --> 00:02:50,330
So ignore the public,

55
00:02:50,330 --> 00:02:53,300
as we're not interested in scope or visibility in Java.

56
00:02:53,300 --> 00:02:55,670
In statically typed languages like Java,

57
00:02:55,670 --> 00:02:58,440
you have to specify the type of every parameter

58
00:02:58,440 --> 00:03:01,800
and also the type of the result that methods return.

59
00:03:01,800 --> 00:03:03,730
So here, void just means that these methods

60
00:03:03,730 --> 00:03:05,560
don't return anything.

61
00:03:06,730 --> 00:03:08,690
Now the first thing to notice

62
00:03:08,690 --> 00:03:11,730
is that there are several versions of this print statement,

63
00:03:11,730 --> 00:03:15,570
each one taking a different type of parameter.

64
00:03:16,620 --> 00:03:19,570
Now Java's a statically typed language

65
00:03:19,570 --> 00:03:22,790
and that means that the type of everything is checked

66
00:03:22,790 --> 00:03:24,580
when the program's compiled.

67
00:03:24,580 --> 00:03:26,800
So if you try to pass a string

68
00:03:26,800 --> 00:03:29,140
to a method that expects an int,

69
00:03:29,140 --> 00:03:31,290
then the programme won't compile.

70
00:03:31,290 --> 00:03:32,610
Now in Python,

71
00:03:32,610 --> 00:03:35,770
the type of something is only of interest when it's used

72
00:03:35,770 --> 00:03:39,390
and that's because Python's a dynamically typed language.

73
00:03:39,390 --> 00:03:41,270
So as you saw in the previous slide,

74
00:03:41,270 --> 00:03:43,930
we've got quite a few versions of that print method here.

75
00:03:43,930 --> 00:03:48,100
In fact, as we go to the next slide, there's more.

76
00:03:49,220 --> 00:03:50,970
So in this slide we can see versions

77
00:03:50,970 --> 00:03:55,140
that accept a char, an int, a long, a float, and a double.

78
00:03:57,930 --> 00:04:00,260
And here we can see the remaining versions

79
00:04:00,260 --> 00:04:05,230
that take an array of characters, a string, and an object.

80
00:04:05,230 --> 00:04:08,530
Now all the methods call another method, write,

81
00:04:08,530 --> 00:04:09,880
to do the printing,

82
00:04:09,880 --> 00:04:11,620
but what most of them have in common

83
00:04:11,620 --> 00:04:14,590
is that they call the String class' valueOf method

84
00:04:14,590 --> 00:04:18,380
to get the string that should be printed.

85
00:04:18,380 --> 00:04:21,490
Now the char and string versions are slightly different.

86
00:04:21,490 --> 00:04:23,100
A string is already a string

87
00:04:23,100 --> 00:04:26,420
so there's no need to do anything to convert it into one.

88
00:04:26,420 --> 00:04:29,680
And an array of characters is close enough to a string

89
00:04:29,680 --> 00:04:33,520
that there's no conversion needed there either.

90
00:04:33,520 --> 00:04:37,080
But all the other methods use this String.valueOf method

91
00:04:37,080 --> 00:04:41,250
to get the string representation of the thing to be printed.

92
00:04:43,770 --> 00:04:46,780
By the way, this is what's meant by overloading methods.

93
00:04:46,780 --> 00:04:49,100
You create different versions of the method

94
00:04:49,100 --> 00:04:50,970
that take different parameters

95
00:04:50,970 --> 00:04:53,960
and the compiler decides which one to use

96
00:04:53,960 --> 00:04:57,980
based on the number and type of the parameters passed to it.

97
00:04:57,980 --> 00:05:02,140
Now overloading isn't possible in Python and isn't necessary

98
00:05:02,140 --> 00:05:04,330
and we've seen how to get the same effect

99
00:05:04,330 --> 00:05:06,380
as having different numbers of parameters,

100
00:05:06,380 --> 00:05:09,920
using named parameters with default values.

101
00:05:09,920 --> 00:05:11,410
We automatically get the ability

102
00:05:11,410 --> 00:05:13,580
to pass parameters of different types

103
00:05:13,580 --> 00:05:16,560
because Python doesn't check the type of variables

104
00:05:16,560 --> 00:05:18,730
when it compiles the code.

105
00:05:20,640 --> 00:05:23,590
So in a statically typed language like Java,

106
00:05:23,590 --> 00:05:25,280
if you want to print a string

107
00:05:25,280 --> 00:05:28,230
then the compiler calls a version of the print method

108
00:05:28,230 --> 00:05:30,060
that can print strings.

109
00:05:30,060 --> 00:05:31,670
And if you wanna print an int

110
00:05:31,670 --> 00:05:35,040
then the compiler calls the version that deals with int.

111
00:05:35,040 --> 00:05:38,290
And similarly, with the last method on the slide,

112
00:05:38,290 --> 00:05:39,960
to print an object,

113
00:05:39,960 --> 00:05:43,170
the compiler calls this version that accepts a parameter

114
00:05:43,170 --> 00:05:44,940
whose type is Object.

115
00:05:44,940 --> 00:05:46,570
Now where it gets interesting

116
00:05:46,570 --> 00:05:49,590
and also relevant to us as Python programmers

117
00:05:49,590 --> 00:05:52,200
is what happens in the valueOf method

118
00:05:52,200 --> 00:05:55,370
so let's actually have a look at that.

119
00:05:57,060 --> 00:05:59,640
Once again, the methods have been overloaded

120
00:05:59,640 --> 00:06:02,430
to cope with the various types of the parameters

121
00:06:02,430 --> 00:06:04,010
that can be passed.

122
00:06:05,050 --> 00:06:08,320
Now the interesting thing here is that none of these methods

123
00:06:08,320 --> 00:06:12,750
attempts to work out what the value should be.

124
00:06:12,750 --> 00:06:13,880
In all cases,

125
00:06:13,880 --> 00:06:17,700
the valueOf method delegates the job of producing the string

126
00:06:17,700 --> 00:06:19,530
to the class involved.

127
00:06:21,340 --> 00:06:22,960
So if we wanna print an int,

128
00:06:22,960 --> 00:06:26,080
the method calls the Integer class' toString method.

129
00:06:26,080 --> 00:06:29,280
Similarly for Long, Float, and Double,

130
00:06:29,280 --> 00:06:31,160
the toString method's called

131
00:06:31,160 --> 00:06:34,530
to get the string representations of the object.

132
00:06:34,530 --> 00:06:37,180
And it's the same for the other types too,

133
00:06:37,180 --> 00:06:38,800
they just wouldn't fit on the screen

134
00:06:38,800 --> 00:06:41,980
so the valueOf method delegates the task of deciding

135
00:06:41,980 --> 00:06:44,960
what the string representation of each class should be,

136
00:06:44,960 --> 00:06:46,740
to the class itself.

137
00:06:46,740 --> 00:06:50,280
Now if valueOf just delegates the task to the class,

138
00:06:50,280 --> 00:06:53,730
it doesn't really need to know what class it's dealing with.

139
00:06:53,730 --> 00:06:55,350
In other words, whatever it gets,

140
00:06:55,350 --> 00:06:57,680
it could just call the toString method

141
00:06:57,680 --> 00:06:59,220
and return the result.

142
00:06:59,220 --> 00:07:02,440
And that turns out to be exactly the approach

143
00:07:02,440 --> 00:07:03,940
that Python takes.

144
00:07:07,230 --> 00:07:08,060
Now I'm not gonna go

145
00:07:08,060 --> 00:07:10,970
into the pros and cons of Java versus Python,

146
00:07:10,970 --> 00:07:14,970
nor of statically versus dynamically typed languages.

147
00:07:14,970 --> 00:07:17,600
I enjoy programming in both Java and Python

148
00:07:17,600 --> 00:07:19,990
and each have their own uses.

149
00:07:19,990 --> 00:07:23,300
What's important is the different philosophies adopted

150
00:07:23,300 --> 00:07:25,400
by the two languages.

151
00:07:25,400 --> 00:07:29,370
Now in Java, you have to specify exactly what type of object

152
00:07:29,370 --> 00:07:30,630
you'll be dealing with.

153
00:07:30,630 --> 00:07:32,950
Otherwise, the code won't even compile.

154
00:07:32,950 --> 00:07:34,790
And that means that every method

155
00:07:34,790 --> 00:07:38,960
knows exactly what it can do with the arguments it receives.

156
00:07:41,570 --> 00:07:44,170
Now Python takes a completely different approach.

157
00:07:44,170 --> 00:07:46,940
It doesn't care about what something is,

158
00:07:46,940 --> 00:07:50,250
it's only interested in how each thing behaves.

159
00:07:50,250 --> 00:07:53,170
So Python focuses on what something does,

160
00:07:53,170 --> 00:07:56,420
without worrying about what type it is.

161
00:07:59,350 --> 00:08:00,840
Now in both languages,

162
00:08:00,840 --> 00:08:05,420
classes inherit from the topmost base class called object

163
00:08:05,420 --> 00:08:08,770
and this base class defines a basic implementation

164
00:08:08,770 --> 00:08:12,030
of the toString method, in the case of Java,

165
00:08:12,030 --> 00:08:14,780
and the __str__ method in Python.

166
00:08:17,060 --> 00:08:19,960
Now the default implementation isn't very pretty,

167
00:08:19,960 --> 00:08:23,080
it just returns the name of the class and a hash code

168
00:08:23,080 --> 00:08:26,380
or the address in memory where the object lives.

169
00:08:26,380 --> 00:08:27,880
Now in both languages,

170
00:08:27,880 --> 00:08:30,430
the polymorphic behaviour of the classes,

171
00:08:30,430 --> 00:08:33,010
in the case of the toString and str methods,

172
00:08:33,010 --> 00:08:35,760
is implemented using inheritance.

173
00:08:38,110 --> 00:08:40,580
So polymorphism basically means

174
00:08:40,580 --> 00:08:44,350
that objects can be more than one thing at the same time.

175
00:08:44,350 --> 00:08:45,860
And then when int is a number,

176
00:08:45,860 --> 00:08:48,740
so it's something you can use to perform arithmetic,

177
00:08:48,740 --> 00:08:51,520
but it's also something that can be printed.

178
00:08:51,520 --> 00:08:55,210
So inheritance is one way to implement polymorphism.

179
00:08:55,210 --> 00:08:58,110
So in this example of making things printable,

180
00:08:58,110 --> 00:09:00,040
every object can be printed,

181
00:09:00,040 --> 00:09:03,780
as well as used for whatever else it does.

182
00:09:03,780 --> 00:09:06,220
Now this is possible because every object

183
00:09:06,220 --> 00:09:09,640
automatically inherits the __str__ method

184
00:09:11,460 --> 00:09:14,620
from it's object base class in Python.

185
00:09:16,730 --> 00:09:18,750
Now inheritance isn't the only way

186
00:09:18,750 --> 00:09:20,820
to implement polymorphism.

187
00:09:20,820 --> 00:09:22,900
Consider a ball and an orange.

188
00:09:22,900 --> 00:09:24,690
They both have a similar shape

189
00:09:24,690 --> 00:09:26,350
so we could juggle with balls

190
00:09:26,350 --> 00:09:28,490
and we could also juggle with oranges,

191
00:09:28,490 --> 00:09:30,370
if we can juggle at all of course,

192
00:09:30,370 --> 00:09:32,810
but they don't inherit their round shape

193
00:09:32,810 --> 00:09:34,910
from any common ancestor.

194
00:09:34,910 --> 00:09:37,800
So a ball and an orange are totally unrelated,

195
00:09:37,800 --> 00:09:40,180
but they can still share some properties

196
00:09:40,180 --> 00:09:43,680
without inheriting them from a base class.

197
00:09:45,090 --> 00:09:49,310
So to a juggler, balls and oranges have similar behaviour.

198
00:09:49,310 --> 00:09:50,710
To a hungry person,

199
00:09:50,710 --> 00:09:54,390
an orange probably has more in common with a loaf of bread

200
00:09:54,390 --> 00:09:56,240
because both can be eaten.

201
00:09:56,240 --> 00:09:59,600
So to stretch the example one more time before I move on,

202
00:09:59,600 --> 00:10:01,420
a gardener may be more interested

203
00:10:01,420 --> 00:10:03,490
in what happens when we plant the orange

204
00:10:03,490 --> 00:10:06,470
and might consider it to have more in common with an acorn,

205
00:10:06,470 --> 00:10:08,840
both can be used to grow a tree.

206
00:10:08,840 --> 00:10:12,170
Okay so going back to our print example.

207
00:10:13,830 --> 00:10:15,600
The print function in Python

208
00:10:15,600 --> 00:10:18,040
doesn't have to cater for the possibility

209
00:10:18,040 --> 00:10:20,190
that the thing it's being asked to print

210
00:10:20,190 --> 00:10:22,820
may not have a suitable method to return a string.

211
00:10:22,820 --> 00:10:25,900
And that's because every class automatically inherits

212
00:10:25,900 --> 00:10:28,780
the method from the object base class.

213
00:10:28,780 --> 00:10:29,870
So that's fine here,

214
00:10:29,870 --> 00:10:31,230
the print function

215
00:10:31,230 --> 00:10:33,880
can cope with anything that's passed to it

216
00:10:33,880 --> 00:10:35,350
because whatever it is,

217
00:10:35,350 --> 00:10:39,520
it's guaranteed to have a string method, str method.

218
00:10:40,850 --> 00:10:43,460
But what bout our enemies in Python?

219
00:10:43,460 --> 00:10:44,480
If we wrote a function

220
00:10:44,480 --> 00:10:46,660
that accepted an Enemy as a parameter

221
00:10:46,660 --> 00:10:49,810
and called the take_damage method of its parameter,

222
00:10:49,810 --> 00:10:52,910
there's no real guarantee that the object we passed to it

223
00:10:52,910 --> 00:10:56,430
would have a take_damage method in Python.

224
00:10:56,430 --> 00:10:59,340
Now we could pass a Player instance to it, for example,

225
00:10:59,340 --> 00:11:03,510
and we haven't given our Player class that method.

226
00:11:04,520 --> 00:11:06,610
Now in Java, that wouldn't be a problem.

227
00:11:06,610 --> 00:11:08,460
We'd have to specify Enemy, say,

228
00:11:08,460 --> 00:11:10,200
as the type of the parameter

229
00:11:10,200 --> 00:11:11,610
and the compiler would then check

230
00:11:11,610 --> 00:11:15,650
that anything we passed did inherit from the Enemy class.

231
00:11:15,650 --> 00:11:18,750
Now in Python though, there's no such checking.

232
00:11:18,750 --> 00:11:21,270
Python isn't interested in the type of objects,

233
00:11:21,270 --> 00:11:23,440
it's only interested in their behaviour

234
00:11:23,440 --> 00:11:25,520
at the time they're used.

235
00:11:26,630 --> 00:11:28,870
Okay so let's end the video here.

236
00:11:28,870 --> 00:11:31,660
In the next video, let's see how all this relates

237
00:11:31,660 --> 00:11:32,960
to Python code.

238
00:11:32,960 --> 00:11:35,020
See you in the next video.

