Los usuarios de Ruby, ya sean creados por (c)attr_accessor
o de forma manual, parecen ser los únicos métodos que necesitan la calificación self.
cuando se accede a ella dentro de la clase. Esto parece poner Rubí solo el mundo de los idiomas:¿Por qué los setters de Ruby necesitan "self"? calificación dentro de la clase?
- Todos los métodos necesitan
self
/this
(como Perl, y creo que Javascript) - No hay métodos requieren
self
/this
es (C#, Java) - Sólo los emisores necesitan
self
/this
(Ruby?)
La mejor comparación es C# y Ruby, porque ambos idiomas admiten métodos de acceso que funcionan sintácticamente igual que insta clase nce variables: foo.x = y
, y = foo.x
. C# los llama propiedades.
Aquí hay un ejemplo simple; el mismo programa en Ruby entonces C#:
class A
def qwerty; @q; end # manual getter
def qwerty=(value); @q = value; end # manual setter, but attr_accessor is same
def asdf; self.qwerty = 4; end # "self." is necessary in ruby?
def xxx; asdf; end # we can invoke nonsetters w/o "self."
def dump; puts "qwerty = #{qwerty}"; end
end
a = A.new
a.xxx
a.dump
quita el self.qwerty =()
y falla (Rubí 1.8.6 en Linux & OS X). Ahora C#:
using System;
public class A {
public A() {}
int q;
public int qwerty {
get { return q; }
set { q = value; }
}
public void asdf() { qwerty = 4; } // C# setters work w/o "this."
public void xxx() { asdf(); } // are just like other methods
public void dump() { Console.WriteLine("qwerty = {0}", qwerty); }
}
public class Test {
public static void Main() {
A a = new A();
a.xxx();
a.dump();
}
}
Pregunta: ¿Es esto verdad? ¿Hay otras ocasiones además de instaladores donde el yo es necesario? Es decir, ¿hay otras ocasiones en que un método de Ruby no se pueda invocarsin?
Ciertamente hay muchos casos en que el auto se convierte en necesario. Esto no es aplicable sólo a Ruby, para ser claros:
using System;
public class A {
public A() {}
public int test { get { return 4; }}
public int useVariable() {
int test = 5;
return test;
}
public int useMethod() {
int test = 5;
return this.test;
}
}
public class Test {
public static void Main() {
A a = new A();
Console.WriteLine("{0}", a.useVariable()); // prints 5
Console.WriteLine("{0}", a.useMethod()); // prints 4
}
}
misma ambigüedad se resuelve de la misma manera. Sin embargo, aunque sutil que estoy preguntando por el caso en el que
- Un método tiene ha definido, y
- Sin variable local se ha definido, y
nos encontramos con
qwerty = 4
que es ambiguo: ¿se trata de una invocación a un método o una nueva asignación de variable local?
@ Mike Piedra
Hola! Entiendo y aprecio los puntos que ha hecho y su ejemplo fue excelente. Créanme cuando digo, si tuviera suficiente reputación, votaría su respuesta.Sin embargo, aún en desacuerdo:
- en una cuestión de semántica, y
- en un punto central de hecho
primer reclamo, no sin ironía, estamos teniendo un debate semántico sobre la significado de 'ambigüedad'.
Cuando se trata de la semántica del lenguaje de programación y programación (el asunto de esta pregunta), seguramente admitiría un amplio espectro de la noción 'ambigüedad'. Vamos a adoptar alguna notación azar:
- ambigua: léxica ambigüedad (lex debe 'mirar hacia adelante')
- ambiguo: gramatical ambigüedad (yacc debe ceder ante el análisis árbol de análisis sintáctico)
- ambigua: la ambigüedad saber todo en el momento de la ejecución
(y también hay basura entre 2-3). Todas estas categorías se resuelven por reuniendo más información contextual, mirando cada vez más globalmente. Así que cuando se decir,
"qwerty = 4" es inequívoco en C# cuando no hay ninguna variable definida ...
no podía estar más de acuerdo. Pero por la misma razón, estoy diciendo
"qwerty = 4" es no-ambiguo en rubí (tal como existe ahora)
"qwerty = 4" es ambiguo en C#
Y aún no nos estamos contradiciendo. Por último, aquí es donde realmente en desacuerdo: Cualquiera de rubí podría o no podría ser implementado sin más construcciones del lenguaje de tal manera que,
Por "qwerty = 4," rubí sin ambigüedades invoca un colocador existente si hay
no hay una variable local definida
Usted dice que no. Yo digo si; puede existir otro ruby que se comporte exactamente como la corriente en todos los sentidos, excepto "qwerty = 4" define una nueva variable cuando no existe el establecimiento y no existe local, invoca al ajustador si existe un y lo asigna al local si existe. Acepto completamente que I podría estar equivocado. De hecho, una razón por la que podría estar equivocado sería interesante.
Déjame explicarte.
Imagine que está escribiendo un nuevo lenguaje OO con métodos de acceso buscando como instancias vars (como ruby & C#).Es probable que empieces con gramáticas conceptuales algo como:
var = expr // assignment
method = expr // setter method invocation
Pero el analizador-compilador (ni siquiera el tiempo de ejecución) se vomitar, porque incluso después de toda la entrada se asimiló no hay manera de saber lo que la gramática es pertinente. Te enfrentas a una elección clásica. No puedo estar seguro de los detalles, pero básicamente rubí hace esto:
var = expr // assignment (new or existing)
// method = expr, disallow setter method invocation without .
que es por eso que es no-ambiguo, mientras que y C# hace esto:
symbol = expr // push 'symbol=' onto parse tree and decide later
// if local variable is def'd somewhere in scope: assignment
// else if a setter is def'd in scope: invocation
para C#, 'más tarde 'todavía está en tiempo de compilación.
Estoy seguro de que ruby podría hacer lo mismo, pero 'later' tendría que ser en tiempo de ejecución, porque como ben señala que no se sabe hasta que se ejecute la sentencia que se aplica el caso .
Mi pregunta nunca tuvo la intención de decir "¿realmente necesito el 'yo'?" o "¿qué se está evitando la posible ambigüedad?" Más bien, quería saber por qué se hizo esta elección particular de ? Tal vez no es el rendimiento. Es posible que simplemente consiguió el trabajo hecho, o se consideró más adecuado para permitir siempre una 1-liner local para reemplazar un método (un requisito caso bastante raro) ...
Pero Soy una especie de lo que sugiere que la el lenguaje más dinámico puede ser el que pospone esta decisión por más tiempo, y elige la semántica basada en la información más contextual : así que si no tiene local y definió un setter, usaría el setter. ¿No es por lo que nos gusta ruby, smalltalk, objc, porque la invocación al método se decide en tiempo de ejecución, ofreciendo máxima expresividad?
PHP también requiere '$ this->' al acceder a variables de instancias. Eso me hace volar todo el tiempo. – Chloe
Un receptor explícito solo es necesario para los métodos de clase, no para los métodos de instancia. –
Acepto - Tampoco me gusta este método para resolver el amibuity. Viola el principio de la menor sorpresa. – Dogweather