Mówi się, że gdy mamy klasę Point
i wie jak wykonać point * 3
jak następuje:W języku Ruby, jak działa funkcja Coerce()?
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
wyjściowa:
#<Point:0x336094 @x=1, @y=2>
#<Point:0x335fa4 @x=3, @y=6>
ale wtedy
3 * point
nie jest rozumiane:
Point
nie może być zmuszany doFixnum
(TypeError
)
Więc musimy dodatkowo określić metodę instancji coerce
:
class Point
def coerce(something)
[self, something]
end
end
p 3 * point
wyjściowa:
#<Point:0x3c45a88 @x=3, @y=6>
Tak jest powiedział, że 3 * point
jest taki sam jak 3.*(point)
. Oznacza to, że metoda instancji *
przyjmuje argument point
i wywołuje obiekt 3
.
Teraz, ponieważ ta metoda *
nie wie, jak pomnożyć punkt, więc
point.coerce(3)
będzie nazwany, i wrócić tablicy:
[point, 3]
a następnie *
jest raz ponownie zastosowany, czy to prawda?
Teraz, to jest zrozumiałe, a teraz mamy nową Point
obiekt, jako wykonywane metodą instancji *
klasy Point
.
Pytanie brzmi:
Kto powołuje
point.coerce(3)
? Czy to Ruby automatycznie, czy jest to jakiś kod w metodzie*
zFixnum
przez wychwycenie wyjątku? Czy to przez oświadczeniecase
, że jeśli nie zna jednego ze znanych typów, to zadzwońcoerce
?Czy zawsze trzeba zwrócić tablicę 2 elementów? Czy to nie może być tablica? Czy może to być zestaw 3 elementów?
I czy reguła, że oryginalny operator (lub metoda)
*
zostanie wywołany na elemencie 0, z argumentem elementu 1? (Element 0 i element 1 to dwa elementy w tej tablicy zwrócone przezcoerce
.) Kto to robi? Czy robi to Ruby, czy jest to zrobione przez kod wFixnum
? Jeśli robi się to za pomocą kodu wFixnum
, to jest to "konwencja", którą wszyscy przestrzegają podczas przymusu?Więc może to być kod w
*
zFixnum
robi coś takiego: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
Tak naprawdę trudno coś dodać do metody
Fixnum
„s instancjicoerce
? To już ma dużo kodu w nim i nie możemy po prostu dodać kilka wierszy w celu zwiększenia go (ale będziemy kiedykolwiek chcesz?)coerce
w klasiePoint
jest dość ogólny i współpracuje z*
lub+
, ponieważ są przechodnie. A jeśli to nie jest przechodnia, takich jak definiujemy minus Fixnum być:point = Point.new(100,100) point - 20 #=> (80,80) 20 - point #=> (-80,-80)
To jest doskonałe pytanie! Jestem bardzo szczęśliwy, że go znalazłem, ponieważ przeszkadzało mi to i aż do teraz nie sądziłem, że można go rozwiązać! – sandstrom
Dobre pytanie. Dzięki za umieszczenie go. Dzięki temu zaoszczędzę wiele czasu na pomieszanie inżynierów. – VaidAbhishek