1
00:00:02,081 --> 00:00:07,077
In this video, we're going to talk about
Coercions which is a feature of type

2
00:00:07,077 --> 00:00:12,098
systems that appears in many languages and
we will be looking specifically how

3
00:00:12,098 --> 00:00:21,604
coercions are done in Java. Java allows
primitive types to be coerced in certain

4
00:00:21,604 --> 00:00:27,410
context. And, coerced means converted from
one type to another. So here's an example,

5
00:00:27,410 --> 00:00:33,243
lets take the expression one + 2.0 and the
difficulty with this expression is that

6
00:00:33,243 --> 00:00:38,043
the, the one here is, is an integer and
the 2.0 is a floating point number. And

7
00:00:38,043 --> 00:00:42,814
there is no way to add an int to a float
directly. We either have to convert the

8
00:00:42,814 --> 00:00:47,779
integer to a float and then do the add as
floating point numbers or convert the

9
00:00:47,779 --> 00:00:52,562
floating point number to an integer and
then do the addition as integer addition.

10
00:00:52,562 --> 00:00:57,086
So they have to be converted to a common
representation, before we can actually do

11
00:00:57,086 --> 00:01:02,029
the operation. And the normal thing to do,
and the thing that Java does, is to

12
00:01:02,029 --> 00:01:06,675
convert the integer to the floating point
number 1.0. Now, a coercion the right way

13
00:01:06,675 --> 00:01:11,608
I think, to think of coercions is they're
really just primitive functions that the

14
00:01:11,608 --> 00:01:16,207
compiler inserts for you. So it's like,
you left out a function call and the

15
00:01:16,207 --> 00:01:20,261
compiler notices that and puts it in. So,
in this particular example, what would be

16
00:01:20,261 --> 00:01:25,042
the function call? Well, there, we can
think of there being a primitive function

17
00:01:25,042 --> 00:01:30,059
that converts integers to floating point
numbers in the obvious way. And so really

18
00:01:30,059 --> 00:01:36,452
this expression here gets converted to the
expression into float applied to the

19
00:01:36,452 --> 00:01:43,516
number one plus 2.0. All right. So
coercions are probably best thought of as

20
00:01:43,516 --> 00:01:48,776
a convenience for you, the programmer to
let you avoid having to write some

21
00:01:48,776 --> 00:01:53,853
function calls. And, so where it is
obvious that a type conversion is going on

22
00:01:54,050 --> 00:01:59,556
the compiler can insert the function that
performs that type conversion for you. And

23
00:01:59,556 --> 00:02:04,665
most languages really have extensive
coercions so the conversions are very,

24
00:02:04,665 --> 00:02:10,468
very common particularly between numeric
types and so this is not just Java. This

25
00:02:10,468 --> 00:02:15,751
is really many different programming
languages of all styles that have lots of

26
00:02:15,751 --> 00:02:21,881
differe nt kinds of coercions. Now, Java
in particular distinguishes two kinds of

27
00:02:21,881 --> 00:02:27,296
coercions and casts. You have widening
coercions and these will always succeed.

28
00:02:27,296 --> 00:02:32,117
Alright, so that means that Java will
always put them in and there will never be

29
00:02:32,117 --> 00:02:37,335
any complaining from the compiler or the
runtime system about them and we already

30
00:02:37,335 --> 00:02:42,701
saw one of those, so the conversion from
int to float is an example of a widening

31
00:02:42,701 --> 00:02:47,733
cast. Now, narrowing casts may fail if the
data can't be converted to the desired

32
00:02:47,733 --> 00:02:52,592
type. So in particular, float to int well,
this will work fine. Something like 2.0

33
00:02:52,592 --> 00:02:56,667
can be converted in obvious way to two but
if you're converting something that

34
00:02:56,667 --> 00:03:00,640
doesn't have an integer representation
something say like 2.5 you know, there's a

35
00:03:00,640 --> 00:03:05,581
question of what we should do here. Okay,
and for such narrowing casts, where there

36
00:03:05,581 --> 00:03:10,825
isn't a, a clear mapping, whether we
should go or, you know or whether we

37
00:03:10,825 --> 00:03:16,613
should try here or round up, or whatever
then Java will actually complain and not

38
00:03:16,806 --> 00:03:23,095
let you do it. Okay perhaps for better
example of the kind of narrowing cast

39
00:03:23,095 --> 00:03:31,251
that's that Java will complain about is
something like a down cast. So if I have

40
00:03:31,526 --> 00:03:38,491
two classes A and B. And B is a subtype of
A and then I have something of type A.

41
00:03:38,491 --> 00:03:44,677
Well, I can cast it to B. I can say, let's
say I have X which is a type A and then I

42
00:03:44,677 --> 00:03:50,437
can have an expression where I try to
convert x to a B object. So here I have a

43
00:03:50,437 --> 00:03:55,855
cast, I've indicated that I want to treat
this expression x as a B object and this

44
00:03:55,855 --> 00:04:00,711
will type check, okay. So the, the
compiler will let this through since B is

45
00:04:00,711 --> 00:04:05,000
subtype of A. But at run time, it's
actually going to check whether x is

46
00:04:05,000 --> 00:04:10,336
actually a B object and if it's not you're
going to get an exception. So this can

47
00:04:10,336 --> 00:04:15,099
fail at run time if the object thatt x
actually holds at the point of the cast is

48
00:04:15,099 --> 00:04:19,446
not a B object. So the rule in Java is
that narrowing cast must be explicit. You

49
00:04:19,446 --> 00:04:24,955
have to put the function in yourself. You
have to put in the typecase in the code so

50
00:04:24,955 --> 00:04:30,004
that it's obvious that you really want to
do it, but widening casts in coercions can

51
00:04:30,004 --> 00:04:34,734
be implicit, so it's alright. If you're
widening, if you're either promoting to a

52
00:04:34,734 --> 00:04:39,936
super type or you are converting between
initial type where it's clear that the,

53
00:04:39,936 --> 00:04:45,608
one type embeds in the other then those
can be filled in for you by the compiler.

54
00:04:45,608 --> 00:04:51,894
And here's a little Java trivia question.
So it turns out that there is one type in

55
00:04:51,894 --> 00:04:57,229
Java for which there are no coercions or
casts defined. Okay so there are no

56
00:04:57,430 --> 00:05:03,290
implicit conversions or even explicit
conversions from that type to any other

57
00:05:03,290 --> 00:05:08,354
type. And the answer to the question,
which is the only one, is bool. Okay so

58
00:05:08,354 --> 00:05:16,456
only the type boolean has no conercions or
casts to another type. Now personally, I'm

59
00:05:16,456 --> 00:05:21,527
not a big fan of coercions. I think that
it's clearly a convenience for

60
00:05:21,527 --> 00:05:26,983
programmers, it's clearly something that
is widely accepted as being necessary in

61
00:05:26,983 --> 00:05:32,641
programming languages because casts,
implicit casts and conversions are so

62
00:05:32,641 --> 00:05:39,266
ubiquitous but I do think that it tends to
lead to programs that have behavior that's

63
00:05:39,266 --> 00:05:44,245
different from what the programmer
probably expected. And, here's a good

64
00:05:44,245 --> 00:05:49,066
example from the language PL/1, which
recalls stood for Programming Language one

65
00:05:49,066 --> 00:05:54,075
designed by IBM in the 1960s. And had
many, many features in it so we've talked

66
00:05:54,075 --> 00:05:59,667
about PL/1 a few times in this class. And
one thing that PL/1 had was very extensive

67
00:05:59,846 --> 00:06:05,103
cast and coercions and this could lead us
to some surprising behaviors. So here's an

68
00:06:05,103 --> 00:06:11,397
example we have a, A, B, and C are strings
of three characters so it's important to

69
00:06:11,397 --> 00:06:17,053
know here that the length three is part of
the type. So B is string '123' C is '456'

70
00:06:17,053 --> 00:06:22,904
and then A is going to be B + c and the
question is what is A? And, and you

71
00:06:22,904 --> 00:06:29,073
probably won't guess, so let me show you
what I think is the right answer. So first

72
00:06:29,073 --> 00:06:34,439
of all the question is what happens with
this + operation here? Well, so that is

73
00:06:34,439 --> 00:06:40,494
going to be interpreted as an integer + so
B and C are both going to be cast to

74
00:06:40,494 --> 00:06:45,959
integers and the, and this will be done as
a integer arithmetic. So B will get

75
00:06:45,959 --> 00:06:52,644
converted to the number 123. C will get
conver ted to the number 456, okay? And

76
00:06:52,644 --> 00:07:00,450
then we'll add them and we'll get out the
number 579. Okay, so the result of this

77
00:07:00,450 --> 00:07:07,153
expression is 579 but A is also a string
of three characters so this has to be cast

78
00:07:07,153 --> 00:07:12,456
back to a string. Now, it turns out that
this cast happens in two steps. First

79
00:07:12,456 --> 00:07:18,079
this, this number here is cast to a string
of the default length, okay. And the

80
00:07:18,079 --> 00:07:25,016
default length happens to be six so this
is cast to a string looks like this.

81
00:07:25,016 --> 00:07:30,992
There's three blanks followed by 579. And
then that string of six characters is

82
00:07:30,992 --> 00:07:35,735
converted to a string of three characters.
And we just take the first three

83
00:07:35,737 --> 00:07:42,535
characters and so we get out that, and so
the answer is that this program stores a

84
00:07:42,535 --> 00:07:48,018
string of three blanks in A. Which is
probably not what was expected.
