Version française
Home     About     Download     Resources     Contact us    
Browse thread
state pattern...
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ 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