Las clausuras de multimétodos actúan como multimétodos. Recuérdese la definición que de multimétodos da la wikipedia:
Multiple dispatch or multimethods is the feature of some object-oriented programming languages in which a function or method can be dynamically dispatched based on the run time (dynamic) type of more than one of its arguments. This is an extension of single dispatch polymorphism where a method call is dynamically dispatched based on the actual derived type of the object. Multiple dispatch generalizes the dynamic dispatching to work with a combination of two or more objects.
generaciondecodigos@nereida:~/Lgroovy/closures$ cat -n multipledispatch.groovy 1 #!/usr/bin/env groovy 2 /* 3 Multiple dispatch or multimethods is the feature of some object-oriented 4 programming languages in which a function or method can be dynamically 5 dispatched based on the run time (dynamic) type of more than one 6 of its arguments. This is an extension of single dispatch polymorphism 7 where a method call is dynamically dispatched based on the actual 8 derived type of the object. Multiple dispatch generalizes the dynamic 9 dispatching to work with a combination of two or more objects. 10 */ 11 class MultiMethod { 12 int f(String val) { 13 val.length() 14 } 15 16 int f(List list) { 17 list.size() 18 } 19 20 int f(int x, int y) { 21 x+y 22 } 23 } 24 25 x = new MultiMethod() 26 27 println "Using method call:" 28 println "On a string: ${x.f('string argument')}" 29 println "On a list: ${x.f([1, 2, 3, 4, 'string'])}" 30 println "On numbers: ${x.f(3, 4)}" 31 32 c = x.&f 33 34 println "Using closure:" 35 println "On a string: ${c('string argument')}" 36 println "On a list: ${c([1, 2, 3, 4, 'string'])}" 37 println "On numbers: ${c(3, 4)}" generaciondecodigos@nereida:~/Lgroovy/closures$Sigue el resultado de una ejecución:
generaciondecodigos@nereida:~/Lgroovy/closures$ ./multipledispatch.groovy Using method call: On a string: 15 On a list: 5 On numbers: 7 Using closure: On a string: 15 On a list: 5 On numbers: 7
Cuando se trabaja con multimétodos pueden surgir dudas sobre que método concreto será llamado. ¿Que métodos serán llamados en este ejemplo?
generaciondecodigos@nereida:~/Lgroovy/closures$ cat -n mm.groovy 1 #!/usr/bin/env groovy 2 class Person { 3 String name 4 5 Person(String name) { 6 this.name = name 7 } 8 9 Person() { 10 this.name = "" 11 } 12 13 boolean equals(Object o) { 14 println("equals(Object o)") 15 // delegate on Groovy equality 16 name == o 17 } 18 19 boolean equals(Person emp) { 20 println("equals(Person emp)") 21 name == emp.name 22 } 23 } 24 25 void test1() { 26 println "==================== test1" 27 Object e1 = new Person("Juana") 28 Object e2 = new Person("Juana") 29 println(e1.equals(e2)) // Person 30 println(e1.equals(e1)) // Person 31 println(e1.equals("Juana")) // Object 32 } 33 34 void test2() { 35 println "==================== test2" 36 Person e1 = new Person("Juana") 37 Person e2 = new Person("Juana") 38 println(e1.equals(e2)) // Person 39 println(e1.equals(e1)) // Person 40 println(e1.equals("Juana")) // Object 41 } 42 43 44 void test3() { 45 println "==================== test3" 46 e1 = new Person("Juana") 47 e2 = new Person("Juana") 48 println(e1.equals(e2)) // Person 49 println(e1.equals(e1)) // Person 50 println(e1.equals("Juana")) // Object 51 } 52 53 54 test1() 55 test2() 56 test3()En la primera prueba los objetos son explícitamente declarados de la clase Object. En la segunda de la clase
Person
. En la tercera no hay declaración explícita.
El resultado de las ejecuciones es el mismo en los tres casos:
generaciondecodigos@nereida:~/Lgroovy/closures$ ./mm.groovy ==================== test1 equals(Person emp) true equals(Person emp) true equals(Object o) true ==================== test2 equals(Person emp) true equals(Person emp) true equals(Object o) true ==================== test3 equals(Person emp) true equals(Person emp) true equals(Object o) true
Casiano Rodríguez León