Certaines personnes (développeurs Ruby, Python...) aiment le duck typing. Pour ma part, je préfère le typage statique, fort et inféré, même si le typage dynamique a parfois ses avantages. En F#, il est possible d'obtenir du duck typing: il suffit d'utiliser l'introspection. Voici une petite classe pour d'exemple :
open System.Reflection type Duck(value: obj) = let mutable value = value let mutable ty = value.GetType() member d.Type = ty member d.Cast<'a>() = unbox<'a> value member d.Exec(str, args) = Duck (ty.InvokeMember(str, BindingFlags.GetProperty ||| BindingFlags.InvokeMethod, null, value, args)) member d.X(str) = d.Exec(str, [||]) member d.X(str, arg1) = d.Exec(str, [|box arg1|]) member d.X(str, arg1, arg2) = d.Exec(str, [|box arg1; box arg2|]) member d.Item with get str = d.Exec(str, [||]) member d.Val with get() = value and set (x:obj) = value <- x; ty <- value.GetType()
Et voici un exemple d'utilisation :
let a = Duck 42 a.Val <- "test" // modifie a: il contient maintenant une chaine a.["Length"] // renvoie 4 a.X("Contains", "st") // exécute une méthode - renvoie true let b = Duck [1; 2; 3] b.Val <- b.["Length"] b.Type.ToString() // renvoie "System.Int32" printfn "%d" (b.Cast()) // affiche 3
La méthode Cast est utilisée pour obtenir une valeur typée. b.Cast<int>() essaie de renvoyer un int (la conversion est testée à l'exécution). L'annotation de type n'est pas toujours nécessaire, du fait de l'inférence de type.
> let length d : int = (Duck d).["Length"].Cast();; val length : 'a -> int > length "test";; val it : int = 4 > length [1; 2];; val it : int = 2
Bien sûr, tout ce code n'est pas sûr : les noms des méthodes peuvent être calculés à l'exécution, peuvent provenir d'entrées utilisateur ou encore contenir des fautes de frappe. Dès que l'on appelle la méthode Cast, on revient dans le monde sûr et statiquement vérifié de F#.
By Laurent Le Brun, Friday 30 May 2008 :: [FR] Cours F# :: #38



Comments
1. On Tuesday 2 June 2009 at 11:31, by jcm
2. On Tuesday 2 June 2009 at 18:22, by Laurent
Leave a comment
Comments are closed.