Il est dit que lorsque nous avons une classe Point
et sait comment effectuer point * 3
comme suit:
class Point
def initialize(x,y)
@x, @y = x, y
end
def *(c)
Point.new(@x * c, @y * c)
end
end
point = Point.new(1,2)
p point
p point * 3
Sortie:
#<Point:0x336094 @x=1, @y=2>
#<Point:0x335fa4 @x=3, @y=6>
mais alors,
3 * point
n'est pas compris:
Point
ne peut pas être contraintFixnum
(TypeError
)
Donc, nous avons besoin de définir une méthode d'instance, coerce
:
class Point
def coerce(something)
[self, something]
end
end
p 3 * point
Sortie:
#<Point:0x3c45a88 @x=3, @y=6>
Donc, il est dit qu' 3 * point
est le même que 3.*(point)
. Qui est, la méthode d'instance *
prend un argument point
et invoquer sur l'objet 3
.
Maintenant, étant donné que cette méthode *
ne sait pas comment multiplier un point, de sorte
point.coerce(3)
sera appelé, et obtenir un tableau:
[point, 3]
et puis, *
est encore une fois appliquée, est-ce vrai?
Maintenant, cela est compris et nous avons maintenant un nouveau Point
objet, telle qu'effectuée par la méthode d'instance *
de la Point
classe.
La question est:
Qui invoque
point.coerce(3)
? Est-il Ruby automatiquement, ou est-ce un code à l'intérieur d'*
méthode deFixnum
par l'interception d'une exception? Ou est-il encase
déclaration que quand il ne sait pas l'un des types connus, puis appelezcoerce
?N'
coerce
toujours besoin de retourner un tableau de 2 éléments? Peut-elle pas être ensemble? Ou peut-il être un tableau de 3 éléments?-
Et la règle est que, l'original de l'opérateur (ou une méthode)
*
sera alors appelée sur l'élément 0, avec l'argument de l'élément 1? (L'élément 0 et l'élément 1 sont les deux éléments dans ce tableau retourné parcoerce
.) Qui est-elle? Est-il fait en Ruby ou est-il fait par code enFixnum
? Si c'est fait par code enFixnum
, alors que c'est une "convention" que tout le monde suit lorsque vous faites une contrainte?Ainsi pourrait-il être le code en
*
deFixnum
de faire quelque chose comme ceci:class Fixnum def *(something) if (something.is_a? ...) else if ... # other type / class else if ... # other type / class else # it is not a type / class I know array = something.coerce(self) return array[0].*(array[1]) # or just return array[0] * array[1] end end end
Donc, il est vraiment difficile d'ajouter quelque chose à l'
Fixnum
s'méthode d'instancecoerce
? Il a déjà beaucoup de code et on ne peut pas simplement ajouter quelques lignes à l'améliorer (mais pourrons-nous jamais?)-
L'
coerce
dans laPoint
classe est assez générique, et il fonctionne avec*
ou+
parce qu'ils sont transitifs. Si ce n'est pas transitive, comme si l'on définit le Point moins Fixnum:point = Point.new(100,100) point - 20 #=> (80,80) 20 - point #=> (-80,-80)