In Ruby, wie funktioniert zwingen() tatsächlich funktioniert?

Es wird gesagt, dass, wenn wir eine Klasse Point und weiß, wie man führen point * 3 wie folgt:

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

Ausgabe:

#<Point:0x336094 @x=1, @y=2>
#<Point:0x335fa4 @x=3, @y=6>

aber dann,

3 * point

nicht verstanden:

Point nicht genötigt in Fixnum (TypeError)

Also brauchen wir, um weiter zu definieren, eine Instanz-Methode coerce:

class Point
  def coerce(something)
    [self, something]
  end
end

p 3 * point

Ausgabe:

#<Point:0x3c45a88 @x=3, @y=6>

Also es wird gesagt, dass 3 * point ist das gleiche wie 3.*(point). Das heißt, die Instanz-Methode * argument point und rufen auf dem Objekt 3.

Nun, da diese Methode * weiß nicht, wie zu multiplizieren, ein Punkt, so

point.coerce(3)

genannt werden, und sich wieder ein array:

[point, 3]

dann * ist wieder einmal angewendet, ist das wahr?

Nun, dies ist verstanden und wir haben jetzt eine neue Point Objekt, wie ausgeführt, durch die Instanz-Methode * des Point Klasse.

Die Frage ist:

  1. Wer ruft point.coerce(3)? Ist es Ruby automatisch, oder ist es einige code innerhalb von * Methode der Fixnum durch das fangen einer exception? Oder ist es durch case Aussage, dass, wenn Sie nicht wissen, einer der bekannten Arten, dann rufen Sie coerce?

  2. Tut coerce immer brauchen, um wieder ein array mit 2 Elementen? Kann es sein, kein array? Oder kann es sein, ein array mit 3 Elementen?

  3. Und ist die Regel, dass der original-operator (oder Methode) * wird dann aufgerufen werden, die auf element 0, mit dem argument des Elements 1? (Element 0 und element 1 sind die zwei Elemente im array zurückgegeben coerce.) Wer tut es? Ist es getan, von Ruby oder ist es getan, indem Sie code in Fixnum? Wenn es durch code in Fixnum, dann ist es eine "Konvention", dass ein jeder folgt, wenn dabei ein Zwang?

    Könnte es also sein, den code in * von Fixnum etwas wie das zu tun:

    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
  4. So ist es wirklich schwer etwas hinzufügen Fixnum's Instanz-Methode coerce? Es hat bereits eine Menge code und wir können nicht fügen Sie einfach ein paar Zeilen zu erweitern (aber werden wir das jemals wollen?)

  5. Den coerce im Point Klasse ist generisch gehalten und es funktioniert mit * oder + weil Sie transitiv. Was ist, wenn es ist nicht transitiv, wie wenn wir definieren Punkt minus Fixnum werden:

    point = Point.new(100,100)
    point - 20  #=> (80,80)
    20 - point  #=> (-80,-80)
  • Das ist eine ausgezeichnete Frage! Ich bin so glücklich, ich habe es gefunden weil es mich stört, und bis gerade jetzt ich glaube nicht, es war lösbar!
  • Eine sehr gute Frage. Vielen Dank für die Umsetzung es. Es spart viele Ingenieur-Verwirrung-Stunden, da bin ich sicher.
InformationsquelleAutor nopole | 2010-05-09
Schreibe einen Kommentar