8.6 Representing objects
Records are the fundamental data structures, and they are the basis for various data manipulation models such as relational databases and object-oriented programming. As explained in Chapter12, SML# seamlessly integrate SQL based on record polymorphism. Object-oriented programming is based on a different computation model than functional programming, and we do not hope to represent it in a functional language. However, generic object manipulation underlying object-oriented programming is naturally represented using record polymorphism.
An object has a statue, receives method selector and invoke the designated method on its state. A class can be regarded as the set of methods that belongs to the class. So we can represent a class structure as a record of methods. Each method is coded as a function that takes a state of an object and update it. For example, consider an object in a pointClass having X coordinate, Y coordinate, Color property. An object state can be represented by a reference to a record of the those values such as {X = 1.1, Y = 2.2}. Then a method can be defined as a function that takes an object state as self and update the state. For example, a method to set a value in the X coordinate can be coded as follows.
# fn self => fn x => self := (!self # {X = x});
val it = fn : [’a#{X: ’b}, ’b. ’a ref -> ’b -> unit]
This method can be applied to any objects that contain X attributes. A class can be a record consisting of these methods with appropriate names. For example,pointClass can be defined as below.
val pointClass =
{
getX = fn self => #X (!self),
setX = fn self => fn x => self := (!self # {X = x}),
getY = fn self => #Y (!self),
setY = fn self => fn x => self := (!self # {Y = x}),
getColor = fn self => #Color (!self),
setColor = fn self => fn x => self := (!self # {Color = x})
}
An object receives a message and invoke the corresponding method on itself. In SML#, this is coded below.
local
val state = ref {X = 0.0, Y = 0.0}
in
val myPoint = fn method => method pointClass state
end
We can similarly define an object having Color attribute.
local
val state = ref {X = 0.0, Y = 0.0, Color = "Red"}
in
val myColorPoint = fn method => method pointClass state
end
Under these definition, we can write the following code.
# myPoint # setX 1.0;
val it = () : unit
# myPoint # getX;
val it = 1.0 : real
# myColorPoint # getX;
val it = 0.0 : real
# myColorPoint # getColor;
val it = "Red" : string
# myPoint # getColor;
(interactive):15.1-15.12 Error:
(type inference 007) operator and operand don’t agree
...
As shown in the last example, the system detect all the type errors statically.