Ruby のセッターは、作成されたか手動で作成されたかにかかわらず、クラス自体内でアクセスするときに修飾(c)attr_accessor
が必要な唯一のメソッドのようです。self.
これにより、Ruby だけが言語の世界に置かれているようです。
- すべてのメソッドには
self
/が必要ですthis
(Perl のように、Javascript だと思います) - メソッドは必要ありません
self
/ありませんthis
(C#、Java) - セッターだけが
self
/this
(Ruby?)を必要とします
最適な比較は C# と Ruby です。どちらの言語も、クラス インスタンス変数のように構文的に機能するアクセサ メソッドをサポートしているためです: foo.x = y
, y = foo.x
. C# はそれらをプロパティと呼びます。
簡単な例を次に示します。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
を取り除くself.qwerty =()
と失敗します (Linux および OS X では Ruby 1.8.6)。今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();
}
}
質問: これは本当ですか? セッター以外に self が必要な場面はありますか? つまり、Ruby メソッドをselfなしでは呼び出せない場合は他にありますか?
確かにselfが必要になるケースは多いです。明確にするために、これは Ruby に固有のものではありません。
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
}
}
同じあいまいさは同じ方法で解決されます。しかし、微妙な間、私はケースについて尋ねています
- メソッドが定義されており、かつ
- ローカル変数が定義されていない。
私たちが遭遇する
qwerty = 4
これはメソッドの呼び出しですか、それとも新しいローカル変数の割り当てですか?
@マイク・ストーン
やあ!私はあなたが指摘した点を理解し、感謝しています。あなたの例は素晴らしかったです。私が十分な評判があれば、あなたの回答に賛成票を投じるだろうと私が言うとき、私を信じてください. それでも、私たちはまだ同意しません:
- セマンティクスの問題について、および
- 事実の中心点に
まず、皮肉なことに、「あいまいさ」の意味について意味論的な議論が行われていると主張します。
言語のセマンティクス (この質問の主題) の解析とプログラミングに関して言えば、「あいまいさ」という概念の幅広い範囲を認めるでしょう。ランダムな表記法を採用しましょう。
- ambiguous: 字句のあいまいさ (lex は「先読み」する必要があります)
- あいまい: 文法的なあいまいさ (yacc は解析ツリー分析を延期する必要があります)
- AMBIGUOUS: 実行の瞬間にすべてを知っているあいまいさ
(そして、2〜3の間にジャンクもあります)。これらのカテゴリはすべて、コンテキスト情報をさらに収集し、よりグローバルに調査することで解決されます。だからあなたが言うとき、
「qwerty = 4」は、変数が定義されていない場合、C# では UNAMBIGUOUS です...
私はこれ以上同意できませんでした。しかし、同じ理由で、私は言っています
「qwerty = 4」はRubyで明確です(現在存在するため)
"qwerty = 4" は C# ではあいまいです
そして、私たちはまだ互いに矛盾していません。最後に、ここで私たちは本当に同意しません: ruby は、次のような追加の言語構造なしでは実装できるかできないかのどちらかです。
「qwerty = 4」の場合、ローカル変数が定義されていない場合、ruby UNAMBIGUOUSLY は既存のセッターを呼び出します。
あなたはノーと言います。はいと言います。「 qwerty = 4」は、セッターもローカルも存在しない場合に新しい変数を定義し、存在する場合はセッターを呼び出し、存在する場合はローカルに割り当てます。私は自分が間違っている可能性があることを完全に受け入れます。実際、私が間違っているかもしれない理由は興味深いでしょう。
説明させてください。
インスタンス変数 (ruby や C# など) のように見えるアクセサ メソッドを使用して、新しいオブジェクト指向言語を作成していると想像してください。おそらく、次のような概念文法から始めるでしょう。
var = expr // assignment
method = expr // setter method invocation
しかし、すべての入力が理解された後でも、どの文法が適切であるかを知る方法がないため、パーサー コンパイラ (ランタイムでさえも) は吐き出します。あなたは古典的な選択に直面しています。詳細はわかりませんが、基本的にRubyはこれを行います:
var = expr // assignment (new or existing)
// method = expr, disallow setter method invocation without .
それがあいまいでない理由です.一方、C#はこれを行います:
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
C# の場合、「後で」はまだコンパイル時です。
ルビーでも同じことができると確信していますが、「後で」は実行時に行う必要があります。なぜなら、ベンが指摘しているように、ステートメントが実行されるまでどのケースが適用されるかわからないからです。
私の質問は、「『自分』が本当に必要なのか?」という意味では決してありませんでした。または「回避されている潜在的なあいまいさは何ですか?」むしろ、なぜこの特定の選択がなされたのか知りたかったのですか? 多分それはパフォーマンスではありません。たぶん、仕事が終わっただけか、1ライナーローカルがメソッドをオーバーライドできるようにするのが最善と考えられていました(かなりまれなケースの要件です)...
しかし、私は、最も動的な言語は、この決定を最も長く延期し、最もコンテキスト情報に基づいてセマンティクスを選択する言語である可能性があることを示唆しています。したがって、ローカルがなく、セッターを定義した場合、セッターが使用されます. メソッドの呼び出しは実行時に決定され、表現力が最大限に発揮されるからです。