Browse thread
state pattern...
[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
| Date: | -- (:) |
| From: | Jacques Garrigue <garrigue@m...> |
| Subject: | Re: [Caml-list] state pattern... |
From: Michael Wohlwend <micha-1@fantasymail.de>
> I have modified the code, so that some method(s) of the state
> classes get the context class as parameter; I think it took me 3
> hour to get the type definitions working :-)
>
> Can this be done simpler? It works, although I don't completly
> understand all of it :-)
There is a variety of things you could do to simplify your code.
If you want to keep the polymorphic-method based approach, you can
avoid type annotations in stat1#show an state2#show by writing
(this : #state).
But another way to simplify things is to switch to subtyping.
That is, just have
method show : param -> unit
in class state, and change context to
method show = state_#show (this :> param)
Note also that your definition of state as a recursive type will cause
problems later, if you try to finalize it in a class.
Here is a possibly simpler version of your code.
class type param =
object
method name : string
end
class type ['next] state =
object
method show: param -> unit
method next: 'next
end
class ['state] context s =
object (this:'self)
val name = "context"
val state : _ #state = s
method state : 'state = state
method name = name
method show = state#show (this :> param)
method run = {< state = state#next >}
end
class state1 = object (this : _ #state)
method show c = print_endline ("state1 of " ^ c#name)
method next = new state2
end
and state2 = object (this : _ #state)
method show c = print_endline ("state2 of " ^ c#name)
method next = new state1
end;;
let c = new context (new state1) ;;
c#show;;
let c = c#run;;
c#show;;
Note that there is an intrinsic weakness to the object-oriented
approach in ocaml: state1 and state2 must actually be the same type,
since a method of context cannot return context with a different
parameter.
On the other hand, if you exactly know what a state should be from the
beginning, you can eliminate all type parameters.
class type param =
object
method name : string
end
class type state =
object
method show: param -> unit
method next: state
end
class context s =
object (this)
val name = "context"
val state : state = s
method state = state
method name = name
method show = state#show (this :> param)
method run = {< state = state#next >}
end
class state1 = object (this : #state)
method show c = print_endline ("state1 of " ^ c#name)
method next = new state2
end
and state2 = object (this : #state)
method show c = print_endline ("state2 of " ^ c#name)
method next = new state1
end;;
But then there is little point in using classes... records and
functions would do the job in a clearer way.
Jacques Garrigue