2011-07-12 8 views

Respuesta

8

En cuanto a Python no puedo decir nada nuevo. El self se pasa convencionalmente como el primer parámetro de un método, como dijo pst. De Python docs

A menudo, el primer argumento de un método se llama self. Esto no es más que una convención: el nombre sí mismo no tiene ningún significado especial para Python. Sin embargo, tenga en cuenta que, al no seguir la convención, su código puede ser menos legible para otros programadores de Python, y también es concebible que se escriba un programa de navegador de clases que dependa de dicha convención.

CRuby (o 'MRI') tiene algo similar que sucede bajo el cofre.Cada extensión C puede definir (módulo/clase/singleton) métodos en una clase de Ruby utilizando

  • rb_define_method (instancia)
  • rb_define_singleton_method (clase singleton)
  • rb_define_module_function (clase/módulo)

Las funciones de implementación reales siempre toman VALUE self como su primer argumento, en analogía al modismo de Python. self en estos casos se refiere a la instancia de objeto de este mensaje en particular se ha enviado a, es decir, si tiene

person = Person.new 
person.do_sth 

y do_sth pasaría a ser implementado en C, entonces no habría una función de C correspondiente

VALUE 
person_do_sth(VALUE self) { 
    //do something 
    return self; 
} 

cada dicha aplicación tiene para devolver una (la representación C de un objeto de Rubí) VALUE, que se refiere al hecho de que cada llamada de método o mensaje enviado (a pegarse a Smalltalk jerga) tiene un valor de retorno en Ruby. No existe la función void en Ruby.

Aunque necesitamos pasar self hacia adelante y hacia atrás en el código C de bajo nivel, no necesita hacerlo en el código Ruby, Ruby se encarga de esto por usted. El valor actual de uno mismo se almacena internamente en el contexto de subproceso actual que se ejecuta, por lo que se concede la existencia de self, el mensaje "self" siempre evaluará a algún objeto.

Debido a la naturaleza dinámica de Ruby, el valor real de este objeto al que se hace referencia en self cambia con el alcance actual del código que se interpreta actualmente. Ejecutar este a ver por sí mismo:

puts "#{self} - declared in global scope" # the 'top self' aka 'main' 
class << self 
    puts "#{self} - 'main's singleton class" # main's singleton or 'eigenclass' 
end 

puts "Starting to interpret class A code" 

class A 
    puts "#{self} - When do I get executed!?" # self is class A 

    class << self 
    puts "#{self} - And me!?" # now A's singleton class 
    def a # declaring method in class's singleton class results in class method 
     puts "#{self} - declared in singleton class" # it's A 
    end 
    end 

    def self.b 
    puts "#{self} - declared in class method" # self is class A again -> class method 
    class << self 
     puts "#{self} - declared in Class A's singleton class" # now it's Class A's singleton class 
    end 
    end 

    def c 
    puts "#{self} - declared in instance method" # self is instance of A 
    class << self 
     puts "#{self} - declared in instance's singleton class" # now it's the A instance's singleton class 
    end 
    end 

end 

puts "All so far has happened simply by interpreting A's code" 

a = A.new 
A.a 
A.b 
a.c 

Si desea llamar a un método/enviar un mensaje desde cualquier contexto a self, usted puede hacer esto de manera explícita (por ejemplo self.method) o se omite self como el receptor - a continuación, Por convención, el receptor implícito del mensaje será self.

Una nota interesante al respecto es la interpretación de Ruby de los métodos private, que difiere, p. de la noción de Java de private. métodos privados de Ruby sólo son exigibles mediante el envío de un mensaje usando self como un receptor implícito, es decir

class A 

    def a 
    b 
    end 

    private 

    def b 
    puts "I'm private" 
    end 
end 

a = A.new 
a.a # => I'm private 

obras, mientras que la sustitución de un método por

def a 
    self.b 
end 

elevaría una excepción. Esto implica que algo muy común en Java

class A { 
    private boolean compareUs(A a1, A a2) { ... } 

    public boolean equals(A a1, A a2) { 
     return (a1.compareUs() == a2.compareUs()); 
    } 
} 

no funcionará en Ruby. Ejemplo tonto, pero solo para ilustrar el punto: en Java podemos acceder a métodos privados de otras instancias de la misma clase, esto no sería posible en Ruby porque solo podemos acceder a métodos privados del actual self.

Finalmente, para complicar las cosas un poco más, las funciones instance_eval y class_eval también alterarán el valor de self durante la ejecución.

+1

Bondad. Qué novela;) –

+0

Awesome answer. Gracias :) –

+0

"return (a1.compareUs() == a2.compareUs())" realmente? el método compareUs() necesita 2 parámetros – hihell

14

Ruby y Python son en realidad muy diferentes idiomas (aunque sí comparten muchas similitudes) incluso si Ruby tiene una sintaxis que se puede escribir para parecerse a Python (con la inclusión de palabras clave end) ;-)

Ruby está basado en mensajes (fue muy influenciado por SmallTalk-80) y se envían "mensajes" a los objetos. Ruby admite un receptor implícito (explícitamente conocido como self) para un ámbito determinado. En Ruby selfno es una variable, sino más bien una expresión que evalúa el contexto del objeto actual.

Python se basa en las propiedades (por falta de un término mejor que yo conozca) y es más similar a SELF y JavaScript ya que las funciones se ejecutan directamente (en lugar de enviar mensajes). Python no tiene la palabra clave self y es meramente convencional que self se usa como el nombre del primer parámetro de un método, que es como Python pasa alrededor del contexto actual del objeto.

Happy coding.

9

En Python, my_instance.a_method(an_argument) es solo una abreviatura de MyClass.a_method(my_instance, an_argument). Así, la definición de MyClass.a_method debe tomar dos parámetros:

class MyClass(object): 
    def a_method(self, an_argument): 
     print self # self (the instance) is available in the method 

Como dijo pst, el uso del nombre de la variable self es sólo una convención. También podría tener

class MyClass(object): 
    def a_method(this_instance, an_argument): 
     print this_instance 

y todo funcionaría igual ... pero no lo haga.