Il semble que les classes-types semblent être la norme pour appliquer une opération à de nombreux types différents. Il ne cherche pas les méthodes au moment de l'exécution (bien, il peut, mais pas le modèle pur), mais il pourrait fournir ce que vous voulez.
trait Numeric[T] {
def times(x :T, y : T) : T
}
object Numeric {
implicit val doubleNumeric = new Numeric[Double] {
def times(x : Double, y : Double) = x*y
}
implicit val intNumeric = new Numeric[Int] {
def times(x : Int, y : Int) = x*y
}
}
def square[A : Numeric](x : A) = implicitly[Numeric[A]].times(x,x)
Si vous faites cela dans le REPL scala, assurez-vous que l'objet numérique est un véritable objet compagnon à trait numérique. Vous pouvez le faire en enveloppant la déclaration dans un autre objet, par exemple tmp, puis en important tmp._.
Ensuite, simplement appeler carré avec des valeurs différentes:
scala> square(2)
res6: Int = 4
scala> square(4.0)
res7: Double = 16.0
Scala fournit en fait une classe de type numérique pour une utilisation dans les calculs numériques, voir: http://www.scala-lang.org/api/current/scala/math/Numeric.html
j'ai écrit aussi un article sur le modèle de classe de type dans Scala et les méthodes de l'utiliser pour adapter plusieurs API ou faire plusieurs envois ici: http://suereth.blogspot.com/2010/07/monkey-patching-duck-typing-and-type.html
Si vous google pour "classe de type scala", vous devriez voir beaucoup d'inf ormation.
Partie 2 - Une réponse réelle à?
Si vous voulez vraiment un respond_to dans scala, vous êtes plutôt SOL. C'est parce que respond_to est vraiment un concept dynamique. Vous définissez une méthode sur une classe qui sera appelée si vous essayez d'appeler une méthode sur la classe qui n'existe pas. Scala ne fait pas abstraction des appels de méthode comme le font certaines langages JVM dynamiques. Cela signifie qu'il n'y a pas de hooks dans les appels de méthodes pour intercepter et interagir avec. Le mieux que vous puissiez faire est une forme d'adaptation d'interface, ou une sorte de hook post-compilation orienté aspect pour réécrire le bytecode pour vous. Utilisez peut utiliser peut également être utilisé dans certains cadres AOP: Le proxy dynamique.
scala> object AllPowerfulProxy extends InvocationHandler {
| def invoke(proxy : AnyRef, m : Method, args : Array[AnyRef]) : AnyRef = {
| println(" You really want to call " + m.getName + "?")
| null // Maliciously Evil!
| }
| }
defined module AllPowerfulProxy
scala> def spawn[A : Manifest] : A = {
| val mf = implicitly[Manifest[A]]
| java.lang.reflect.Proxy.newProxyInstance(mf.erasure.getClassLoader,
| Array(mf.erasure),
| AllPowerfulProxy).asInstanceOf[A]
| }
spawn: [A](implicit evidence$1: Manifest[A])A
Maintenant, nous pouvons l'utiliser pour générer des objets sur n'importe quelle interface. Voyons voir ce que nous pouvons faire:
scala> val x = spawn[TestInterface]
You really want to call toString?
java.lang.NullPointerException
at scala.runtime.ScalaRunTime$.stringOf(ScalaRunTime.scala:259)
Vous voyez ce que nous avons fait là-bas? Lorsque le REPL essaie d'appeler toString sur le résultat d'une expression, il l'appelle sur notre proxy dynamique. Puisque le proxy est un espace réservé, l'appel réel est délégué à notre classe AllPowerfulProxy, comment affiche le message: "Vous voulez vraiment appeler toString?". Le REPL frappe ensuite le retour null et déclenche une exception. Vous voyez, l'utilisation de proxies dynamiques déplace les erreurs vers l'exécution, vous devez donc faire très attention lors de l'instanciation des objets et du retour des types corrects. En fonction de la complexité de votre système, vous devriez également vous préoccuper de classLoaders. Si jamais vous obtenez une ClassCastException de Foo à Foo, alors vous savez que vous êtes dans l'enfer du chargeur de classe.
Dans tous les cas, si vous avez d'autres questions sur les proxies dynamiques, n'hésitez pas à demander. Dans les langages à typage statique, il est probablement préférable d'utiliser des classes de type et de migrer vers des modèles de conception en les utilisant au lieu de ceux utilisant respond_to. (Vous serez surpris de ce que vous pouvez accomplir avec les classes de types et le système de types).
Vérifiez http://stackoverflow.com/questions/1988181/pattern-matching-structural-types-in-scala pour une question connexe –
Intéressant, merci. Mais peut-être y a-t-il des avancées qui le rendent plus facile à utiliser maintenant? – Debilski