Point
que represente puntos (x, y)
del plano cartesiano.
to_s
Point
usando el predicado is_a?
.
2 * p
es necesario definir un método
coerce
en la clase Point
:
def coerce(other) [self, other] endLos tipos numéricos definen un método de conversión denominado
coerce
.
Cuando se llama al método *
de 2
: 2*(p)
este llamará primero al método coerce
de Point
y después
intentará multiplicar los elementos del array retornado.
>> 1.1.coerce(1) => [1.0, 1.1] >> r = Rational(1,3) => Rational1, 3 >> r.coerce(2) => [Rational2, 1, Rational1, 3]defina
coerce
de manera que pueda multiplicarse un escalar por un Point
.
-@
:
~/rubytesting/TheRubyProgrammingLanguage/Chapter7ClassesAndModules$ cat -n unaryminus.rb 1 class Tutu 2 def initialize(s) 3 @s = s 4 end 5 6 def -@ 7 @s.reverse 8 end 9 10 def to_s 11 @s 12 end 13 end 14 15 if __FILE__ == $0 16 a = Tutu.new("dlrow olleH") 17 puts -a 18 endAl ejecutarse produce:
~/rubytesting/TheRubyProgrammingLanguage/Chapter7ClassesAndModules$ ruby unaryminus.rb Hello world
[]
de manera que pueda accederse a un punto como si fuera un array
de sólo lectura.
Permite el uso de índices negativos.
También debería poder accederse usando una notación hash. Por ejemplo, el código:
p = Point.new(1,2) puts "#{p[0]}, #{p[1]}" puts "#{p[-2]}, #{p[-1]}" puts "#{p[:x]}, #{p[:y]}" puts "#{p['x']}, #{p['y']}"Debería producir como salida:
$ ruby Point.rb 1, 2 1, 2 1, 2 1, 2Un hash es una estructura de datos que asocia a cada uno de los elementos de un conjunto de objetos denominados claves un valor:
>> n = { :one => 1, :two => 2, :three => 3} => {:one=>1, :two=>2, :three=>3} >> n[:four] = 4 => 4 >> n => {:one=>1, :two=>2, :three=>3, :four=>4} >> b = n[:one]+n[:four] => 5 >> n[:five] => nil >> n.keys => [:one, :two, :three, :four] >> n.values >> n.each { |k,v| puts "value for #{k} is #{v}" } value for one is 1 value for two is 2 value for three is 3 value for four is 4 => [1, 2, 3, 4]
hash
que retorne un código hash de tipo Fixnum.
La clase Hash
compara las claves
usando el predicado eql?
. Este predicado es similar a ==
pero es mas restrictivo. Por ejemplo, en las subclases de Numeric
==
permite la conversión de tipos mientras que eql?
no:
>> 1 == 1.0 => true >> 1.eql?(1.0) => falsePermita que los objetos
Point
puedan ser usados como índices de un hash.
El siguiente código:
p = Point.new(1,2) q = Point.new(1,1) m = { p => 1, q => 2 } puts m[p] puts m[q]deberá producir como salida:
1 2Para eso deberá definir:
hash
de un Point
:
Puede usar con algoritmo de hashcode el descrito
en Effective Java (Addison-Wesley 2001) por Joshua Bloch
eql?
. El predicado deberá retornar true
si el otro objeto es exactamente de la clase
Point
. Véase el método instance_of?
:
>> 4.class => Fixnum >> 4.class.superclass => Integer >> 4.class.superclass.superclass => Numeric >> 4.class.superclass.superclass.superclass => Object >> 4.class.superclass.superclass.superclass.superclass => nil >> 4.instance_of? Fixnum => true >> 4.instance_of? Integer => false >> 4.instance_of? Numeric => false >> 4.is_a? Numeric => true
each
que produzca primero la primera coordenada y después la segunda.
Incluya el módulo
Enumerable
y compruebe que puede usar algunos de los métodos proveídos
por este como all?
y any?
.
==
para que dos puntos sean iguales si sus coordenadas son iguales.
Siguen dos posibles implementaciones:
def ==(o) if o.is_a? Point @x==o.x && @y==o.y else false end end |
def ==(o) @x==o.x && @y==o.y rescue false end |
<=>
guerra de las galaxias de manera que dos Point
se comparan según su distancia
al origen de coordenadas. Si self
es menor que el objeto, <=>
deberá retornar -1
, si son iguales 0
y 1
si es mayor.
Compruebe que puede usar los métodos proveídos por Comparable
.
Este programa:
p = Point.new(1,2) q = Point.new(1,1) r = Point.new(2,1) # It is not a total order relation puts p > r puts p < r puts p == r puts p > qDeberá producir una salida como esta:
false false false true
sort
, min
y max
Point3D
que reutilice y herede de Point
y que tenga las mismas funcionalidades.
Casiano Rodriguez León 2015-01-07