From 1f6b97d29c759a477a676d2bd38b4fe99e46b166 Mon Sep 17 00:00:00 2001 From: Ernesto Bossi Date: Sat, 7 Sep 2019 00:42:34 -0300 Subject: [PATCH] script y comentario --- README.md | 37 ++++++++++++++ script.rb | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 183 insertions(+) create mode 100644 script.rb diff --git a/README.md b/README.md index d034066..63a9868 100644 --- a/README.md +++ b/README.md @@ -99,8 +99,45 @@ metodo.bind(Hijo.new).call #=> 'correr como padre' ~~~ Como vemos los Unbound Methods se escapan al metodo lookup. + +##### Controles sobre unbound methods + +Si bien los Unbound methods se escapan al metodo lookup, cuando se hace el bind se hace previamente un chequeo de que la jerarquia a la que se bindea un unbound method debe ser del mismo tipo al de la clase que pertenecia o bien un tipo de la misma jerarquia, por ejemplo tomando lo que vimos ants tratemos de bindear un metodo a una clase que no es de la jerarquia de Padre/Hijo + +```ruby +class A +end + +metodo = Padre.instance_method(:correr) + +metodo.bind(A.new).call # TypeError (bind argument must be an instance of Padre) +``` + +por lo que solo podremos bindear el UnboundMethod de correr perteneciente a la clase Padre a una instancia de Padre o de una subclase, por lo que se ajusta a lo que nos devuelve `kind_of?` + +```ruby +Hijo.new.kind_of? Padre # verdadero +Padre.new.kind_of? Padre # verdadero +A.new.kind_of? Padre # falso +``` + +Es lo mismo que nos dide la documentacion en https://ruby-doc.org/core-2.6.1/UnboundMethod.html + +Incluso este control es algo que no podemos sobreescribir ya que es un control hecho en la implementacion de MRi de Ruby: + +https://github.com/ruby/ruby/blob/dd81af7b6a7539473b6d7a7e35637b4a7d986523/proc.c#L2403 + +y que finalmente llama al metodo `convert_umethod_to_method_components` + +https://github.com/ruby/ruby/blob/dd81af7b6a7539473b6d7a7e35637b4a7d986523/proc.c#L2328 + +Por lo que una instancia de UnboundMethod, al menos en MRi no podremos bindearlo en cualquier otro metodo, siempre hay algunas restricciones... + +Sigamos.... + Tambien podemos preguntarle cosas a los metodos. + ~~~ruby metodo = atila.method(:atacar) #=> # metodo.arity #=> 1 diff --git a/script.rb b/script.rb new file mode 100644 index 0000000..8808476 --- /dev/null +++ b/script.rb @@ -0,0 +1,146 @@ +require_relative 'age' +atila = Guerrero.new +atila.class +atila.class.superclass + +atila.methods +Guerrero.instance_methods +Guerrero.instance_methods(false) + +# Envio de mensajes + +atila.send(:potencial_ofensivo) #=> 20 +atila.send(:descansar) #=> 110 + +# con send no existen los metodos privados, la seguridad es una sensacion +class A + private + def metodo_privado + 'cosa privada, no te metas' + end +end +objeto = A.new +objeto.metodo_privado #=> NoMethodError: private method `metodo_privado' called for # +objeto.send(:metodo_privado) #=> "cosa privada, no te metas" + +# bound/unbound method + +metodo = atila.method(:potencial_ofensivo) +metodo.call + +class Padre + def correr + 'correr como padre' + end +end + +class Hijo < Padre + def correr + 'correr como hijo' + end +end +metodo = Padre.instance_method(:correr) #=># +metodo.bind(Hijo.new).call #=> 'correr como padre' + +metodo = atila.method(:atacar) +metodo.arity +metodo.parameters +metodo.owner + +# variables + +atila.instance_variables +atila.instance_variable_get(:@energia) +atila.instance_variable_set(:@energia, 50) +atila.instance_variable_get(:@energia) +atila + +# Open Classes + +class String + def importante + self + '!' + end + end + 'aprobe'.importante #=> "aprobe!" + + #Cambiar métodos + class Fixnum + def +(x) + 123 + end + end + 2+2 + +#define method + +Guerrero.send(:define_method, :saluda) { + 'Hola' +} +Guerrero.new.saluda #=> "Hola" + +# define singleton method + +atila.define_singleton_method(:saluda) { + 'Hola soy Atila' +} +atila.saluda +Guerrero.new.saluda + + +#### Segunda parte...... + +zorro = Espadachin.new(Espada.new(123)) + +# Eigenclasses + +Peloton.cobarde([]) + +Peloton.methods.include? :cobarde #=> true +Peloton.class.instance_methods.include? :new #=> true +Peloton.class.instance_methods.include? :cobarde #=> false + +Peloton.singleton_class.instance_methods(false) #=> [:cobarde, :descansador] + +module W + def m + 123 + end +end + +a = Guerrero.new +a.singleton_class.include W +a.m #=> 123 +b = Guerrero.new +b.extend W +b.m #=>123 + +## + +atila = Guerrero.new +atila.singleton_class.send(:define_method, :comerse_un_pollo, proc { @energia += 20 }) +atila.energia +atila.comerse_un_pollo +atila.energia +Guerrero.new.comerse_un_pollo # NoMethodError + +## + +atila.singleton_class.send(:attr_accessor, :edad) +atila.edad = 5 +atila.edad #=> 5 +Guerrero.new.edad #=> NoMethodError + +Guerrero.ancestors #=> [Guerrero, Defensor, Atacante, Object, PP::ObjectMixin, Kernel, BasicObject] +Guerrero.new.singleton_class.ancestors + +class Guerrero + def self.gritar +    'haaaa' + end +end + +atila.gritar #=> NoMethodError +Guerrero.gritar #=> haaaa + +Espadachin.gritar #=>haaaa \ No newline at end of file