﻿1
00:00:00,400 --> 00:00:03,560
Hello. In this sequence
we'll be looking at Reflection,

2
00:00:03,720 --> 00:00:08,640
the capacity for Introspection
in Pharo and why it's useful.

3
00:00:09,600 --> 00:00:11,880
A reflective system,

4
00:00:12,040 --> 00:00:15,960
reflection is divided
into 2 major families,

5
00:00:16,120 --> 00:00:18,000
Introspection

6
00:00:18,160 --> 00:00:21,240
is a program's ability
to observe its own state,

7
00:00:21,400 --> 00:00:25,880
Intercession is a program's ability
to modify itself.

8
00:00:26,040 --> 00:00:29,040
To modify its own state
or interpretation.

9
00:00:30,640 --> 00:00:34,560
Reification is a concept that consists

10
00:00:34,720 --> 00:00:39,760
of making explicit (objects) things
that are normally implicit.

11
00:00:39,920 --> 00:00:43,920
For example, the execution stack

12
00:00:44,080 --> 00:00:49,400
in Pharo is explicit,
but can be got as a classic object.

13
00:00:49,920 --> 00:00:55,280
More classically, a class in Pharo
is a totally classic object.

14
00:00:55,480 --> 00:00:58,960
In other languages,
classes aren't objects.

15
00:01:00,040 --> 00:01:02,160
A reflective system, as I said,

16
00:01:02,320 --> 00:01:06,600
has its own representation of itself.

17
00:01:06,760 --> 00:01:09,600
It's capable of representing itself,

18
00:01:09,760 --> 00:01:14,840
and it can act on this representation
to modify itself,

19
00:01:15,000 --> 00:01:19,600
and when it modifies itself
it changes its state and representation.

20
00:01:19,760 --> 00:01:22,600
We call it a "causal connection"

21
00:01:22,760 --> 00:01:25,520
between its representation
and its state.

22
00:01:25,680 --> 00:01:27,720
If we change the state,

23
00:01:27,880 --> 00:01:32,520
the system representation changes
as well as the state of the system.

24
00:01:33,000 --> 00:01:37,080
Why is this interesting?
It's interesting because we'll use

25
00:01:37,480 --> 00:01:41,160
this introspection and intercession

26
00:01:41,320 --> 00:01:43,240
to look inside objects.

27
00:01:43,400 --> 00:01:48,800
I'm defining a collection,
which I make an "OrderedCollection"

28
00:01:49,680 --> 00:01:54,680
then I'll use the Pharo Inspector,
which is a tool,

29
00:01:54,840 --> 00:01:57,960
which can look inside this object.

30
00:01:58,120 --> 00:02:02,200
It's an instance object
of the OrderedCollection class,

31
00:02:02,360 --> 00:02:05,840
as we see here,
it has instance variables,

32
00:02:06,000 --> 00:02:07,720
"first index", "last index",

33
00:02:07,880 --> 00:02:10,600
we have the values of this
object's instance variables

34
00:02:10,760 --> 00:02:15,400
so 1, 12 and then
an array of 12 elements, OK?

35
00:02:15,560 --> 00:02:19,400
We might wonder how
this Inspector tool

36
00:02:19,560 --> 00:02:22,000
is able to look inside objects.

37
00:02:22,160 --> 00:02:25,120
How can it see
the internal state of objects?

38
00:02:26,600 --> 00:02:31,160
It uses introspection methods
to look inside the objects,

39
00:02:31,320 --> 00:02:34,360
There are lots of them,
defined as "objects".

40
00:02:34,520 --> 00:02:37,800
So "instVarAt" allows us to see

41
00:02:37,960 --> 00:02:40,960
an instance invariable
according to its number.

42
00:02:41,120 --> 00:02:44,480
I'll see instance variable
number 1 of this object.

43
00:02:44,640 --> 00:02:49,600
I can modify instance variable number 1
of this object by setting a new value,

44
00:02:49,760 --> 00:02:52,160
or I can access an instance
variable by its name,

45
00:02:52,320 --> 00:02:56,000
or change it by its name,
"instVarNamed put". OK?

46
00:02:58,320 --> 00:03:01,160
Here are some examples.
Typically we create a point,

47
00:03:01,320 --> 00:03:04,880
and then we do...
the point is 10@3

48
00:03:05,040 --> 00:03:07,360
instVarNamed: 'x'.

49
00:03:07,520 --> 00:03:11,760
I'll get the value of the instance
variable called 'x' of this point,

50
00:03:11,920 --> 00:03:14,080
which gives me 10.

51
00:03:14,240 --> 00:03:17,960
Then "instVarNamed: 'x' put:33"

52
00:03:18,120 --> 00:03:21,840
I've changed the value of
the instance variable 'x' of this point.

53
00:03:22,000 --> 00:03:25,680
It's gone from 10 to 33.

54
00:03:25,840 --> 00:03:30,080
I've been able to change
the inner state of an object,

55
00:03:30,240 --> 00:03:34,120
by using introspection and intercession,

56
00:03:34,280 --> 00:03:38,200
particularly intercession,
"instVarNamed put". OK?

57
00:03:38,360 --> 00:03:40,800
The main point is that
we've violated encapsulation.

58
00:03:40,960 --> 00:03:45,560
An external object has modified
this object, without being internal,

59
00:03:45,720 --> 00:03:49,600
so it violates encapsulation
but it's extremely useful

60
00:03:49,760 --> 00:03:52,960
when building tools
and during development.

61
00:03:53,120 --> 00:03:56,840
It's not to be used in the normal
code of an application,

62
00:03:57,000 --> 00:04:00,160
but it's extremely powerful
for building generic tools,

63
00:04:00,320 --> 00:04:02,320
typically code inspectors.

64
00:04:03,680 --> 00:04:07,360
I'll give you another example
of introspection, the class method,

65
00:04:07,520 --> 00:04:11,240
for getting the class of an object.
It's defined in "Object>>class".

66
00:04:11,400 --> 00:04:14,760
I ask this string its class,
it gives me the class string,

67
00:04:14,920 --> 00:04:17,880
this point what is its class,
the class point,

68
00:04:18,040 --> 00:04:21,600
"Smalltalk class",
I can ask the class of the class class.

69
00:04:21,760 --> 00:04:23,840
etcetera, then I add class class...

70
00:04:24,000 --> 00:04:26,560
Basically, I can query the system

71
00:04:26,720 --> 00:04:30,880
by sending the message "class"
to objects to discover their class.

72
00:04:31,320 --> 00:04:34,040
There are many methods
for querying the system.

73
00:04:34,200 --> 00:04:38,360
Here, I take "OrderedCollection"
and send it lots of query messages.

74
00:04:38,520 --> 00:04:41,200
I'll get all of its superclasses,

75
00:04:41,360 --> 00:04:45,520
all of its selectors,
the name of its instance variables,

76
00:04:45,680 --> 00:04:50,680
all of the selectors,
the name of its instance variables,

77
00:04:50,840 --> 00:04:54,120
all of its subclasses, etc...

78
00:04:54,280 --> 00:04:56,160
And all of its lines of code.

79
00:04:57,320 --> 00:05:00,920
All of this allows us to build
top level tools,

80
00:05:01,080 --> 00:05:04,840
such as the navigation system here.

81
00:05:05,000 --> 00:05:09,600
This navigation system lets us
show or browse the system.

82
00:05:09,760 --> 00:05:14,360
For example,
I can see all the classes

83
00:05:15,440 --> 00:05:18,880
that implement the method "#,".

84
00:05:19,040 --> 00:05:21,720
Here we've a window that will open.

85
00:05:21,880 --> 00:05:24,600
We'll see all the implementors of #,

86
00:05:24,760 --> 00:05:29,200
so the class "AbstractFileReference"
implements the method "#,".

87
00:05:29,360 --> 00:05:32,280
I've a list of all the classes
implemented by this method.

88
00:05:33,880 --> 00:05:37,520
Another example,
we'd like to implement

89
00:05:38,280 --> 00:05:41,240
a menu or a button.

90
00:05:41,400 --> 00:05:45,520
By clicking on it, we want to send
a message to the object behind it,

91
00:05:45,680 --> 00:05:48,680
according to the button's name,
for example.

92
00:05:48,840 --> 00:05:53,760
How do I turn a string into a message
to send to an object?

93
00:05:54,560 --> 00:05:59,480
I've an intercession method for that.
"Perform" defined under "object".

94
00:05:59,640 --> 00:06:03,320
I pass it a symbol,
the name of a message to execute,

95
00:06:03,480 --> 00:06:06,360
and it will send this message
to the object in question.

96
00:06:06,520 --> 00:06:10,560
I've a 2nd kind of message,
"perform with".

97
00:06:10,720 --> 00:06:14,960
I can give the name of the symbol,
the name of the method to execute,

98
00:06:15,120 --> 00:06:16,800
and then pass a list of arguments.

99
00:06:16,960 --> 00:06:19,400
An example, if I do "5 factorial"

100
00:06:19,560 --> 00:06:23,280
sending a classic message,
and send the reflective message,

101
00:06:23,440 --> 00:06:28,960
its "5 perform # factorial"
that's a symbol which means,

102
00:06:29,280 --> 00:06:34,680
"Object 5, please execute
or receive the message factorial".

103
00:06:34,880 --> 00:06:39,600
The normal lookup is applied
and these two forms are the same.

104
00:06:40,240 --> 00:06:41,920
Here's another example.

105
00:06:42,120 --> 00:06:44,480
Here we have a code inspector

106
00:06:44,640 --> 00:06:49,600
"Ordered collection", we can see inside
the class "Ordered Collection".

107
00:06:49,760 --> 00:06:54,480
This class contains attributes,

108
00:06:54,640 --> 00:06:57,000
instance variables,
for example "methodDict".

109
00:06:57,160 --> 00:07:01,680
In "methodDict" we see
that the class "OrderedCollection"

110
00:07:01,840 --> 00:07:05,960
comes from "Behaviour"
so it has a "methodDict' here,

111
00:07:06,120 --> 00:07:10,360
an instance of "MethodDictionary"
containing "CompiledMethod".

112
00:07:10,520 --> 00:07:14,360
So we can see
this method dictionary contains

113
00:07:14,520 --> 00:07:17,360
a compiled method here, etc...

114
00:07:17,520 --> 00:07:20,360
another compiled method...
Lots of compiled methods.

115
00:07:20,840 --> 00:07:25,480
We'll be able to ask each
of these compiled methods

116
00:07:25,920 --> 00:07:28,280
for their source code.
If I do "self getSource"

117
00:07:28,440 --> 00:07:30,600
I'll get the source code
of the compiled method.

118
00:07:30,880 --> 00:07:32,200
But we can go further.

119
00:07:32,400 --> 00:07:35,800
A compiled method can be asked
to execute itself directly

120
00:07:35,960 --> 00:07:39,200
with the message,
"valueWithReceiver:arguments".

121
00:07:39,360 --> 00:07:42,200
But watch out!
If I do that, there's no lookup.

122
00:07:42,360 --> 00:07:45,920
Seeing as I already have
a compiled method,

123
00:07:46,080 --> 00:07:48,600
it executes itself directly
without a message.

124
00:07:48,760 --> 00:07:53,520
Here I'll ask the integer class
to get its compiled method "factorial",

125
00:07:53,680 --> 00:07:56,240
which I get from the
class compiled method.

126
00:07:56,400 --> 00:07:59,320
I send it the message,
"valueWithReceiver:arguments".

127
00:07:59,480 --> 00:08:03,200
I pass it the arguments,
the receiver will be 5,

128
00:08:03,360 --> 00:08:06,320
the arguments will be (),
because it's a unary message,

129
00:08:06,480 --> 00:08:08,800
and we'll get the result.

130
00:08:09,760 --> 00:08:14,880
It triggers execution of the
compiled method without lookup.

131
00:08:15,240 --> 00:08:18,360
So to summarize,
reflection is extremely powerful.

132
00:08:18,560 --> 00:08:22,360
We've seen it's something
that allows us to introspect

133
00:08:22,840 --> 00:08:25,240
the whole system
because it represents it

134
00:08:25,400 --> 00:08:26,880
in itself as an object,

135
00:08:27,040 --> 00:08:29,440
but also to modify
the state of the system.

136
00:08:29,600 --> 00:08:33,240
It lets us build tools
in a generic way in all objects.

137
00:08:33,960 --> 00:08:36,400
So you can really talk to objects

138
00:08:36,560 --> 00:08:40,000
with a protocol that's structurally
the same for all objects.

139
00:08:40,160 --> 00:08:43,800
But watch out!
It violates encapsulation.

140
00:08:43,960 --> 00:08:48,080
It isn't used in operational code,
but for tool building.

141
00:08:48,240 --> 00:08:52,840
It facilitates the writing
of code inspectors as we saw,

142
00:08:53,000 --> 00:08:56,560
and you can see how
it's implemented in Pharo.