Ruby setters-qu'elle soit créée par (c)attr_accessor
ou manuellement-semblent être les seules méthodes qui ont besoin d' self.
de qualification lors de l'accès à l'intérieur de la classe elle-même. Cela semble mettre Ruby seul le monde des langues:
- Toutes les méthodes doivent
self
/this
(comme Perl, et je pense que le Javascript) - Pas de méthodes nécessitent
self
/this
est (C#, Java) - Seuls les poseurs besoin d'
self
/this
(Ruby?)
La meilleure comparaison est C# vs Ruby, parce que les deux langues de soutien accesseur des méthodes de travail du point de vue syntaxique comme instance de classe variables: foo.x = y
, y = foo.x
. C# les appelle des propriétés.
Voici un exemple simple: le même programme en Ruby, 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
tenir à l'écart de l' self.qwerty =()
et échec (Ruby 1.8.6 sur Linux et OS X). Maintenant 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();
}
}
Question: Est-ce vrai? Existe-il d'autres occasions d'ailleurs setters où l'auto est-elle nécessaire? I. e., il y a des occasions où un Rubis méthode ne peut pas être invoquée sans auto?
Il y a certainement beaucoup de cas où l'auto devient nécessaire. Ce n'est pas unique à Ruby, juste pour être clair:
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
}
}
Même ambiguïté est résolue de la même manière. Mais bien que subtile, je demande au cas où
- Une méthode a été définie, et
- Pas de variable locale a été défini, et
nous rencontrons
qwerty = 4
ce qui est ambigu: est-ce une invocation de méthode ou d'une nouvelle affectation de variable?
@Mike Stone
Salut! J'comprendre et d'apprécier les points que vous avez fait et de votre exemple était grande. Croyez-moi quand je dis, si j'avais assez de réputation, J'avais vote de votre réponse. Pourtant, nous avons encore pas d'accord:
- sur une question de sémantique, et
- un point central de fait
D'abord je demande, non sans ironie, que nous allons avoir un débat sémantique sur la du sens de "l'ambiguïté'.
Quand il s'agit de l'analyse et du langage de programmation sémantique (le sujet de cette question), vous avez sûrement admettre un large spectre de la notion 'ambiguïté'. Disons simplement adopter un hasard notation:
- ambigu: d'ambiguïté lexicale (lex doit "regarder de l'avant")
- Ambigu: grammaire de l'ambiguïté (yacc doit s'en remettre à analyser-analyse de l'arbre)
- AMBIGU: l'ambiguïté tout savoir au moment de l'exécution
(et il y en indésirable entre 2-3 trop). Toutes ces catégories sont résolus par la collecte de plus contextuelle info, la recherche de plus en plus à l'échelle mondiale. Ainsi, lorsque vous dire,
"qwerty = 4" est sans AMBIGUÏTÉ en C# quand il n'y a pas de variable défini...
Je ne pouvais pas être plus d'accord. Mais, en même temps, je dis
"qwerty = 4" est non-Ambigu en ruby (comme il existe maintenant)
"qwerty = 4" est Ambigu en C#
Et nous ne sommes pas encore se contredire les uns les autres. Enfin, c'est là que nous avons vraiment pas d'accord: Soit ruby pourrait ou ne pourrait pas être mis en œuvre sans plus les constructions de langage tels que,
Pour "qwerty = 4," ruby sans AMBIGUÏTÉ invoque un existant setter si il y
est pas de variable locale définie
Vous dire non. Je dis oui; un autre rubis pourrait exister, qui se comporte exactement comme le courant dans tous les domaines, à l'exception de "qwerty = 4" définit une nouvelle variable lorsque aucun set et pas de local existe, il invoque le setter si l'on existe, et il assigne à l'locale si celle-ci existe. Je suis entièrement d'accepter que je peut-être erroné. En fait, une raison pour laquelle je peux me tromper, ce serait intéressant.
Laissez-moi vous expliquer.
Imaginez que vous écrivez un nouveau langage OO avec les méthodes d'accès à la recherche comme les instances de vars (comme ruby et C#). Vous devriez probablement commencer avec conceptuel des grammaires quelque chose comme:
var = expr // assignment
method = expr // setter method invocation
Mais l'analyseur-compilateur (même pas le moteur d'exécution) va vomir, parce que, même après tous les commentaires est grokked il n'y a aucun moyen de savoir qui de la grammaire est pertinente. Vous êtes face de laquelle un choix classique. Je ne peux pas être sûr de l'détails, mais fondamentalement, ruby fait ceci:
var = expr // assignment (new or existing)
// method = expr, disallow setter method invocation without .
c'est pourquoi il est d'onu-Ambiguë, même si et C# fait ceci:
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
Pour C#, "plus tard" est toujours au moment de la compilation.
Je suis sûr que ruby pourrait faire de même, mais "plus tard" devrait être au moment de l'exécution, parce que comme ben souligne que vous ne savez pas jusqu'à ce que l'instruction est exécutée, auquel cas s'applique.
Ma question n'a jamais été destiné à signifier "ai-je vraiment besoin de le 'soi'.'?" ou de "ce que une ambiguïté potentielle est évitée?" Plutôt, je voulais savoir pourquoi cette particulier choix? C'est peut-être pas la performance. Peut-être qu'il a obtenu l'emploi fait, ou il a été jugé préférable de toujours permettre un 1-liner local pour remplacer un méthode (assez rare cas exigence) ...
Mais je suis en quelque sorte ce qui suggère que les plus dynamiques de la langue pourrait être quelqu'un qui reporte cette décision la plus longue, et choisit la sémantique basé sur les plus contextuelle info: si vous n'avez pas de local et vous avez défini un setter, il devrait utiliser le setter. N'est-ce pas c'est pourquoi nous comme le rubis, smalltalk, objc, parce que l'invocation de méthode est décidé au moment de l'exécution, offrant un maximum d'expressivité?