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]
end
Los 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 end
Al 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